为项目Euler进行单元测试

时间:2010-06-26 12:24:37

标签: unit-testing

我开始讨论项目Euler中的问题,我想用TDD风格来处理它,但是我很难找到不包含代码的问题的数字答案。是否有任何资源包含该数据,以便我可以制作测试用例,告诉我是否正确解决了问题?

我的动机是,我觉得算法是答案,而不是数字。如果我查看其他人的代码示例,就会破坏找出如何来解决问题的挑战。

编辑:我正在寻找没有上下文或算法的答案编号,以便我可以执行以下操作。我知道它更冗长,但我希望能够通过/失败结果告诉我我的算法是否正确,而不是查看其他人的代码示例以了解我是否已正确完成。

import unittest
class ProblemOneTest(unittest.TestCase):
    def test_me(self):
        self.assertEquals(solve_problem_one(),233168)

if __name__ == '__main__':
    print "Problem 1 possible answer: %d" % solve_problem_one()
    sys.exit(unittest.main())

7 个答案:

答案 0 :(得分:11)

TDD和项目欧拉作业不一定顺利。首先,TDD不会帮助您解决任何项目的Euler(PE)问题。这让我想起了一个人通过using TDD“解决数独”的众所周知的尝试。

TDD不是一种设计技巧。它在适用时非常有用,但不要将其视为银弹。

PE问题通常涉及一些以单个数字结尾的繁重计算,这就是答案。为了谨慎应用TDD,我建议将它用于您将开发的数学实用程序,作为解决PE问题的一部分。例如,我的PE的utils模块包含用于计算素数,将数字拆分为数字,检查回文等的函数。该模块有一组测试,因为这些函数 general 足以进行测试。 PE解决方案本身没有测试 - 他们唯一需要的真正测试是最终产生正确的答案。

答案 1 :(得分:4)

项目欧拉网站上的问题页面有一个输入来检查你的答案。这就是我真正需要的。

答案 2 :(得分:2)

是的,您可以根据他们提供的测试数据设置单元测试。

您似乎正在使用Python来解决问题(就像我一样)。我对验证不同组件所做的是对示例数据执行简单的“assert”语句。它运行良好,开销时间更短。此外,当您只需要知道问题30的新更改是否正确时,您无需运行整个测试套件。

Using Assertions Effectively

答案 3 :(得分:1)

单元测试是答案。

问题通常很简单(不是难度,但至少是代码布局),将它们分解成各种方法/类通常是愚蠢的。

答案 4 :(得分:1)

我知道我已经晚了3年,但我想我会分享我是如何通过TDD接近Project Euler的。

我正在使用Python,如果这对你很重要。

我的工作是:

  • 每个问题都会(至少)获得自己的功能,作为进入/退出点,无论它有多么微不足道或愚蠢。如果问题需要您认为将来可能需要的某种功能,问题也可能会得到帮助函数。
  • 大多数项目Euler问题包括测试本身中较小的演示/测试问题。此测试问题说明了您最常解决的问题,但规模较小。
  • 计划使用参数设置您的进入/退出功能,该参数允许该功能解决问题的玩具版本以及更难的全尺寸版本。例如,在problem 12上我的(可笑地命名的)入口点是get_triangle_num_with_n_or_more_divisors(n)。
  • 此时我还没有实现该功能,只是将其命名。现在我将针对此问题编写两个测试:test_example和test_problem。我现在用@unittest.skip('Unimplemented')装饰test_problem,因为我们不知道答案。您的测试文件可能看起来像我的:

    import unittest
    
    from problems.p0014 import get_triangle_num_with_n_or_more_divisors
    
    class TestHighlyDivisibleTriangleNumber(unittest.TestCase):
        def test_example(self):
            self.assertEquals(get_triangle_num_with_n_or_more_divisors(1),
                              1)
            self.assertEquals(get_triangle_num_with_n_or_more_divisors(2),
                              3)
            self.assertEquals(get_triangle_num_with_n_or_more_divisors(6),
                              28)
    
        @unittest.skip('Unimplemented')
        def test_problem(self):
            self.assertEquals(get_triangle_num_with_n_or_more_divisors(500),
                              'TODO: Replace this with answer')
    

现在你正在做Project Euler,TDD风格。您正在使用给出的示例案例来测试您的实现代码。真正唯一的诀窍就是以足够灵活的方式编写实现,以便它可以用来解决练习版和真实版。

然后我坐下来写下get_triangle_num_with_n_or_more_divisors。一旦test_example通过,我试着解决真正的问题;如果它工作,我用真正的答案更新我的test_problem案例, bam 你有一个完整的回归测试来启动。

答案 5 :(得分:0)

尽管这些问题在没有回答的情况下更具挑战性,但谷歌的快速搜索却产生了:

http://code.google.com/p/projecteuler-solutions/wiki/ProjectEulerSolutions

答案 6 :(得分:0)

以为我会分享我的方法:

拥有Project Euler section的Hackerrank遵循TDD范式。它使用未知测试用例对您的算法进行评分。他们提供了一个示例测试用例来帮助您入门。我离线开发并编写其他一些测试用例来验证我的解决方案,以获得更快,更精确的反馈。

哪一个会得到那些案件?您可以手动执行它们,也可以从您自己的强制生成它们,强制在本地运行的代码。这样做的好处在于,您必须自己考虑边缘情况,这是现实生活场景中更典型的情况。

JavaScript中的测试示例:

var cases = [
  {input: '1\n15', output: '45'},
  ...
];

describe('Multiples of 3 and 5', function() {
  cases.forEach((v, i) => {
    it('test case #' + i, function () {
      assert.equal(unit(v.input), v.output);
    })
  });
});

虽然Hackerrank使用stdin和stdout,但我仍然试图将主代码隔离成函数并使用函数式编程。