Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I will not address the problem that your sample code to test clearly have. I'll focus on your question about reusing test code.</p> <p><strong>Important things to keep in mind before even starting:</strong></p> <ol> <li>Tests must be simple (without any logic inside, or very very little).</li> <li>Tests should be readable (they are like code documentation).</li> <li>Tests should be maintainable.</li> </ol> <p>The simplicity of your tests is a must, and while keeping that you'll need to find the right balance between the last two points.</p> <p><strong>One last warning:</strong> Be very very careful when reusing your test code, because if you'll do it wrong your tests will be bugged. Test bugs are hard to spot, but a year from now you may find one, the seed of doubt will be planted and the trust in your tests might decrease. Tests that you don't trust (<em>"oh, that one is failing but nevermind because that other one is failing too, etc..."</em>) are completely and utterly worthless.</p> <hr> <p>Now that we cleared our way let's look at your code. Usually the dynamic part of tests is achieved through context (the <code>setUp</code> and <code>tearDown</code> methods), but in your case things are a little more complex.</p> <blockquote> <p>I want to run a couple of test cases on different function of a module.</p> </blockquote> <p>You don't actually want the <em>same</em> test case to run with a different function, but only the same code. A good testing environment will have (at least) one test case for every function.</p> <p>Since you're looking for the ability to run a previous test case/suite against a partial output of another function, you'll need <a href="http://docs.python.org/py3k/library/functools.html#functools.partial" rel="nofollow noreferrer"><code>functools.partial</code></a> that will let you wrap your function with default arguments.</p> <p>This means that you should start from the bottom, from the simplest tests:</p> <pre><code>def check_valid_range(value, sides): """Check that value is a valid dice rolling""" assert 0 &lt; value &lt;= sides def check_is_int(value): """Check that value is an integer""" assert type(value) is int </code></pre> <p>And then build on top of them (with a little pluggability):</p> <pre><code>class TestRollADice: """roll_a_dice basic tests""" @staticmethod def func_to_test(*args, **kwargs): return diceroller.roll_a_dice(*args, **kwargs) @staticmethod def check_valid_output(value, sides): """Check that value is the self.function is valid""" yield check_valid_range, value, sides yield check_is_int, value def test_3sides(self): """Check valid result for a 3 sides dice""" yield self.check_valid_output, self.func_to_test(3), 3 def test_list_valid_sides(self): """Check valid result for a list of valid sides (sides &gt;= 3)""" sides = list(range(3, 13)) for s in sides: yield self.check_valid_output, self.func_to_test(s), s def test_0_sides_raises_ValueError(self): """0 side dice raise ValueError""" assert_raises(ValueError, self.func_to_test, 0) def test_1_sides_raises_ValueError(self): """1 side dice raise ValueError""" assert_raises(ValueError, self.func_to_test, 1) def test_2_sides_raises_ValueError(self): """2 sides dice raise ValueError""" assert_raises(ValueError, self.func_to_test, 2) def test_minus1_sides_raises_ValueError(self): """-1 side dice raise ValueError""" assert_raises(ValueError, self.func_to_test, -1) </code></pre> <p>These are the minimum amount of tests your <code>roll_a_dice</code> function should have. Try to run <code>nosetests</code> in your package and you'll see two of them failing, see how tests are important!! :)</p> <p>I'm sure you've noticed how the tests name are verbose, it's for readability.</p> <p>Now for the <code>roll_dice</code> the main test class should test those three, four basic values and the baisc errors, because a good should be simple and keep under control what's being tested, I'd say that you might need some functions like:</p> <pre><code>def check_list_length(self, lst, count): """Check that the len(lst) == count""" assert len(lst) == count def check_valid_count(self, count): """Check count &gt; 0""" assert count &gt; 0 class TestRollDice: # ... </code></pre> <p>And now if you want to reuse the old code you can subclass <code>TestRollADice</code>:</p> <pre><code>from functools import partial class TestRollDice_Count1(TestRollADice): @staticmethod def func_to_test(*args, **kwargs): return partial(diceroller.roll_dice, count=1)(*args, **kwargs) </code></pre> <p>And voilà, almost free you'll have twice the tests as before :)</p> <p><strong>Note:</strong> </p> <ol> <li>All the code above could be written in <code>unittest</code> language, but since you asked about <code>nose</code> I wrote with that.</li> <li>There's a minor problem: the docstrings for the passing tests are the same, so in the verbose output they show up twice. It's not a big problem, since if one of those tests should fail you'll be prompted with the test address and that one is unique (and clear since luckly our test names are verbose). I also seem to remember that the docstrings might be disabled or something. So, once again, this is not a big problem, and should be easy to find a workaround, if needed.</li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload