如果要测试一个类似于N皇后问题这样比较复杂的算法,你会怎么写测试?我的意思是,对于这种算法,应该采用什么样的正确方法来进行测试:
有许多解决方案(你不知道/不关心有多少个解决方案),
你只能得到所有可能解决方案的一个小子集,和
验证一个解决方案是否正确可能有点棘手(与算法本身的复杂性相当)。
我知道这些条件在N皇后问题本身中并不存在,但我提到它只是为了提供一个例子。
如果要测试一个类似于N皇后问题这样比较复杂的算法,你会怎么写测试?我的意思是,对于这种算法,应该采用什么样的正确方法来进行测试:
有许多解决方案(你不知道/不关心有多少个解决方案),
你只能得到所有可能解决方案的一个小子集,和
验证一个解决方案是否正确可能有点棘手(与算法本身的复杂性相当)。
我知道这些条件在N皇后问题本身中并不存在,但我提到它只是为了提供一个例子。
在测试复杂算法时,您需要依靠需要验证的“数据”。假设您已经有了某种形式的问题解决方案(数据),您只需采取数据并让算法运行,并查看答案是否匹配。以使用算法解决n-puzzle为例,它是不确定性的,但您有数据来验证解决方案。
算法实际上是最容易进行单元测试的,因为它们没有外部依赖。最好的方法是使用测试驱动开发:确定您想要算法实现的下一个微小需求,为其创建一个测试,然后编写代码以满足该测试(即使这意味着硬编码结果,也不要编写比必要更多的代码)。然后继续进行,根据需要重构代码库,使其更通用并接受更多的用例。当所有用例都被覆盖时,您应该拥有一个坚实的算法实现。
你只能测试你知道可以期望的行为。
你是否知道某些测试数据存在解决方案?例如,你可能手动计算出在8x8棋盘上肯定可以放置六个皇后,或者你可能在书中读到至少存在一种方法将八个皇后放置在8x8棋盘上。然后你可以测试你的程序返回至少一个解决方案(也许你不检查它是否是有效的解决方案)。
你是否知道其他一些测试数据不存在解决方案?例如,你可以很容易地自我说服,在3x3上放置三个皇后或在8x8上放置九个皇后是不可能的。然后测试你的程序返回无解决方案,或抛出预期的异常。
你想测试给定的解决方案是否有效吗?那么你必须编写代码来测试其有效性,并运行此代码,无论它有多复杂。如果它足够复杂,请为它编写测试。如果你很幸运,你的程序可以自然地重构,以便你可以重用其中的一些较小部分来测试你的解决方案(重用这些较小部分是可以的,因为你也已经彻底测试了这些部分,不会“引入相同的错误”)。
最后,一旦您发现了错误,您就有了一个示例,说明程序返回了意外结果。编写一个测试来断言下一次不会返回该结果。
任何程序都无法实现100%的测试覆盖率。您能做的只是测试您知道的情况并有时间编写的测试用例。
有许多问题,创造一种解决方案比检查任何解决方案是否正确更加困难。
对于像N皇后问题这样的情况,您只需要检查棋盘上每行和对角线上是否只有一个皇后,并且在解决方案中是否有N个皇后,就可以知道该解决方案是否有效。
2:
如果已知该问题具有其他算法可用于某些共同的输入集,则尝试使用其他算法测试原始算法以处理它们都适用的输入集。例如,暴力搜索可能有效,或者可预先计算并保存较小范围的输入的结果以供测试。在某些数学问题中,对于一定范围的输入(如平方数或2的幂等),答案更易验证。您至少应该测试这些情况。