How do you generate dynamic (parameterized) unit tests in python?

后端 未结 25 2135
面向向阳花
面向向阳花 2020-11-22 07:09

I have some kind of test data and want to create a unit test for each item. My first idea was to do it like this:

import unittest

l = [[\"foo\", \"a\", \"a\         


        
25条回答
  •  北海茫月
    2020-11-22 07:26

    Meta-programming is fun, but can get on the way. Most solutions here make it difficult to:

    • selectively launch a test
    • point back to the code given test's name

    So, my first suggestion is to follow the simple/explicit path (works with any test runner):

    import unittest
    
    class TestSequence(unittest.TestCase):
    
        def _test_complex_property(self, a, b):
            self.assertEqual(a,b)
    
        def test_foo(self):
            self._test_complex_property("a", "a")
        def test_bar(self):
            self._test_complex_property("a", "b")
        def test_lee(self):
            self._test_complex_property("b", "b")
    
    if __name__ == '__main__':
        unittest.main()
    

    Since we shouldn't repeat ourselves, my second suggestion builds on @Javier's answer: embrace property based testing. Hypothesis library:

    • is "more relentlessly devious about test case generation than us mere humans"
    • will provide simple count-examples
    • works with any test runner
    • has many more interesting features (statistics, additional test output, ...)

      class TestSequence(unittest.TestCase):

      @given(st.text(), st.text())
      def test_complex_property(self, a, b):
          self.assertEqual(a,b)
      

    To test your specific examples, just add:

        @example("a", "a")
        @example("a", "b")
        @example("b", "b")
    

    To run only one particular example, you can comment out the other examples (provided example will be run first). You may want to use @given(st.nothing()). Another option is to replace the whole block by:

        @given(st.just("a"), st.just("b"))
    

    Ok, you don't have distinct test names. But maybe you just need:

    • a descriptive name of the property under test.
    • which input leads to failure (falsifying example).

    Funnier example

提交回复
热议问题