开发者

Making unit tests for project Euler

I'm starting to go through the questions in project Euler, and I'd like to approach it with a TDD style, but I'm having trouble finding the numeric answer to the question that doesn't include the code. Is there any resource with that data so that I can make test cases that will tell me if I've solved the problem correctly?

My motivation for this is that I feel like the algorithm is the answer, not the number. If I look at someone else's code sample, it ruins the challenge of figuring out how to solve the problem.

Edit: I'm looking specifically for the number of the answer with no context or algorithm with it so that I can do something like the following. I know it's more verbose, but I'd like to be able to have a pass/fail result to tell me w开发者_如何学Chether or not my algorithm is correct, rather than looking at someone else's code example to know whether I've done it correctly.

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())


TDD and project Euler assignments don't necessarily go well together. First and foremost, TDD won't help you solve any project Euler (PE) problems. This reminds me of that well known attempt by a guy to "solve Sudoku" by using TDD.

TDD is not a design technique. It can be very useful when applicable, but don't think of it as a silver bullet.

A PE problem usually involves some heavy computation that ends in a single number, which is the answer. To apply TDD mindfully, I recommend using it for the mathematical utilities you will develop as parts of your endeavors to solve PE problems. For example, my utils module for PE consists of functions for computing primes, splitting numbers to digits, checking for palindromes, and so on. This module has a set of tests, because these functions are general enough to be tested. The PE solutions themselves don't have tests - the only real test needed for them is to eventually generate the correct answer.


The problem page on the project Euler website has an input to check your answer. That's all I really need.


Yes, you can setup your unit tests against the test data they give.

It appears that you are using Python to solve the problems (as am I). What I do to validate the different components is to do simple 'assert' statements against the example data. It works well and there is less time overhead. Besides, you don't need to run the entire test suite when you are just needing to know if your new changes for problem 30 are correct.

Using Assertions Effectively


The unit test IS the answer.

The problems are usually so simple (not in terms of difficulty, but at least code layout) that breaking them up into various methods/classes is usually silly.


I know I'm 3 years late to the party but I thought I would share how I am approaching Project Euler via TDD.

I'm working in Python, if that matters to you.

What I do is this:

  • Every problem gets (at a minimum) its own function that serves as an entry/exit point, no matter how trivial or silly it may feel. Problems may also get helper functions if the problem requires some kind of functionality that you think you might need in the future.
  • Most Project Euler questions include a smaller demo/test problem in the test itself. This test problem illustrates what you most solve but on a smaller scale.
  • Plan to set up your entry/exit function with a parameter that allows the function to solve both the toy version of the problem as well as the harder full scale version. For instance, on problem 12 my (ridiculously named) entry point is get_triangle_num_with_n_or_more_divisors(n).
  • At this point I haven't implemented the function, just named it. Now I will write two tests for this problem: test_example and test_problem. I'll decorate test_problem with @unittest.skip('Unimplemented') for now since we don't know the answer. Your test file might look something like mine:

    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')
    

Now you are doing Project Euler, TDD style. You are using the example cases given to test your implementation code. Really the only trick to it is to write your implementation in a flexible enough way that it can be used to solve both the practice version and the real version.

I then sit down and write get_triangle_num_with_n_or_more_divisors. Once test_example is passing, I try to solve the real problem; if it works I update my test_problem case with the real answer and bam you've got a full blown regression test to boot.


Despite the fact that these problems are more of a challenge without an answer to steer towards, a quick google search yielded:

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


Thought I'd share my approach:

Hackerrank, which has a Project Euler section, goes by the TDD paradigm. It scores your algorithm using unknown test cases. They provide one sample test case to get you started. I develop offline and write some other test cases to validate my solution to get quicker and more precise feedback.

Where would one get those cases? You can do them by hand, and perhaps generate them from your own brute forcing code which is run locally. The beauty of this is that you must account for edge cases yourself, which is more typical of a real life scenario.

Example of tests in 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);
    })
  });
});

Although Hackerrank uses stdin and stdout, I still try to isolate the main code into a function and employ functional programming.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜