source

Python에서 동적(파라미터화) 단위 테스트를 생성하는 방법은 무엇입니까?

manycodes 2022. 12. 25. 09:43
반응형

Python에서 동적(파라미터화) 단위 테스트를 생성하는 방법은 무엇입니까?

테스트 데이터가 있어서 항목별로 단위 테스트를 만들고 싶습니다.제 첫 번째 생각은 이렇게 하는 것이었습니다.

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequence(unittest.TestCase):
    def testsample(self):
        for name, a,b in l:
            print "test", name
            self.assertEqual(a,b)

if __name__ == '__main__':
    unittest.main()

단점은 모든 데이터를 한 번의 테스트로 처리한다는 것입니다.각 아이템에 대해 1개의 테스트를 즉시 생성하고 싶습니다.좋은 의견이라도 있나?

이것을 "파라미터화"라고 합니다.

이 접근방식을 지원하는 툴이 몇 가지 있습니다.예:

결과 코드는 다음과 같습니다.

from parameterized import parameterized

class TestSequence(unittest.TestCase):
    @parameterized.expand([
        ["foo", "a", "a",],
        ["bar", "a", "b"],
        ["lee", "b", "b"],
    ])
    def test_sequence(self, name, a, b):
        self.assertEqual(a,b)

그러면 테스트가 생성됩니다.

test_sequence_0_foo (__main__.TestSequence) ... ok
test_sequence_1_bar (__main__.TestSequence) ... FAIL
test_sequence_2_lee (__main__.TestSequence) ... ok

======================================================================
FAIL: test_sequence_1_bar (__main__.TestSequence)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/parameterized/parameterized.py", line 233, in <lambda>
    standalone_func = lambda *a: func(*(a + p.args), **p.kwargs)
  File "x.py", line 12, in test_sequence
    self.assertEqual(a,b)
AssertionError: 'a' != 'b'

과거의 이유로, 2008년경에 원래의 회답은 남깁니다.

다음과 같은 것을 사용합니다.

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequense(unittest.TestCase):
    pass

def test_generator(a, b):
    def test(self):
        self.assertEqual(a,b)
    return test

if __name__ == '__main__':
    for t in l:
        test_name = 'test_%s' % t[0]
        test = test_generator(t[1], t[2])
        setattr(TestSequense, test_name, test)
    unittest.main()

unittest 사용(3.4 이후)

.4 , 라이브러리 Python 3.4는 Python 3.4를 합니다.unittest에는 ""가 .subTest콘텍스트 매니저

다음의 메뉴얼을 참조해 주세요.

예:

from unittest import TestCase

param_list = [('a', 'a'), ('a', 'b'), ('b', 'b')]

class TestDemonstrateSubtest(TestCase):
    def test_works_as_expected(self):
        for p1, p2 in param_list:
            with self.subTest():
                self.assertEqual(p1, p2)

및 을 " "로 .subTest():

with self.subTest(msg="Checking if p1 equals p2", p1=p1, p2=p2):

사용

코 테스트 프레임워크지원합니다.

예(아래 코드는 테스트를 포함하는 파일의 전체 내용입니다.)

param_list = [('a', 'a'), ('a', 'b'), ('b', 'b')]

def test_generator():
    for params in param_list:
        yield check_em, params[0], params[1]

def check_em(a, b):
    assert a == b

nosetests 명령어 출력:

> nosetests -v
testgen.test_generator('a', 'a') ... ok
testgen.test_generator('a', 'b') ... FAIL
testgen.test_generator('b', 'b') ... ok

======================================================================
FAIL: testgen.test_generator('a', 'b')
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.5/site-packages/nose-0.10.1-py2.5.egg/nose/case.py", line 203, in runTest
    self.test(*self.arg)
  File "testgen.py", line 7, in check_em
    assert a == b
AssertionError

----------------------------------------------------------------------
Ran 3 tests in 0.006s

FAILED (failures=1)

메타클래스를 사용하면 우아하게 해결할 수 있습니다.

import unittest

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]

class TestSequenceMeta(type):
    def __new__(mcs, name, bases, dict):

        def gen_test(a, b):
            def test(self):
                self.assertEqual(a, b)
            return test

        for tname, a, b in l:
            test_name = "test_%s" % tname
            dict[test_name] = gen_test(a,b)
        return type.__new__(mcs, name, bases, dict)

class TestSequence(unittest.TestCase):
    __metaclass__ = TestSequenceMeta

if __name__ == '__main__':
    unittest.main()

Python 3.4에서는 이 목적을 위해 unittest에 서브테스트가 도입되었습니다.상세한 것에 대하여는, 메뉴얼을 참조해 주세요.TestCase.subTest는 테스트에서 아사트를 분리하여 장애가 파라미터 정보로 보고되지만 테스트 실행을 중지하지는 않습니다.다음은 설명서의 예입니다.

class NumbersTest(unittest.TestCase):

def test_even(self):
    """
    Test that numbers between 0 and 5 are all even.
    """
    for i in range(0, 6):
        with self.subTest(i=i):
            self.assertEqual(i % 2, 0)

테스트 실행의 출력은 다음과 같습니다.

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

이 또한 unittest2의 일부이므로 이전 버전의 Python에서 사용할 수 있습니다.

load_tests는 TestSuite를 동적으로 작성하기 위해 2.7에서 도입된 거의 알려지지 않은 메커니즘입니다.이를 통해 매개 변수화된 테스트를 쉽게 만들 수 있습니다.

예를 들어 다음과 같습니다.

import unittest

class GeneralTestCase(unittest.TestCase):
    def __init__(self, methodName, param1=None, param2=None):
        super(GeneralTestCase, self).__init__(methodName)

        self.param1 = param1
        self.param2 = param2

    def runTest(self):
        pass  # Test that depends on param 1 and 2.


def load_tests(loader, tests, pattern):
    test_cases = unittest.TestSuite()
    for p1, p2 in [(1, 2), (3, 4)]:
        test_cases.addTest(GeneralTestCase('runTest', p1, p2))
    return test_cases

이 코드는 load_tests에 의해 반환된 TestSuite의 모든 TestCase를 실행합니다.다른 테스트는 디스커버리 메커니즘에 의해 자동으로 실행되지 않습니다.

또는 다음 티켓에 표시된 상속을 사용할 수도 있습니다.http://bugs.python.org/msg151444

pytest를 사용하면 됩니다.파일만 써주세요.test_me.py다음 중 하나:

import pytest

@pytest.mark.parametrize('name, left, right', [['foo', 'a', 'a'],
                                               ['bar', 'a', 'b'],
                                               ['baz', 'b', 'b']])
def test_me(name, left, right):
    assert left == right, name

시험을 하세요.py.test --tb=short test_me.py을 사용하다

=========================== test session starts ============================
platform darwin -- Python 2.7.6 -- py-1.4.23 -- pytest-2.6.1
collected 3 items

test_me.py .F.

================================= FAILURES =================================
_____________________________ test_me[bar-a-b] _____________________________
test_me.py:8: in test_me
    assert left == right, name
E   AssertionError: bar
==================== 1 failed, 2 passed in 0.01 seconds ====================

간단해!또한 pytest에는 다음과 같은 기능이 있습니다.fixtures,mark,assert 등등.

ddt 라이브러리를 사용합니다.테스트 방법에 대한 간단한 데코레이터를 추가합니다.

import unittest
from ddt import ddt, data
from mycode import larger_than_two

@ddt
class FooTestCase(unittest.TestCase):

    @data(3, 4, 12, 23)
    def test_larger_than_two(self, value):
        self.assertTrue(larger_than_two(value))

    @data(1, -3, 2, 0)
    def test_not_larger_than_two(self, value):
        self.assertFalse(larger_than_two(value))

은 설치 합니다.pip요.nose 라이브러리와의 unittest★★★★★★ 。

TestScenarios 라이브러리를 사용해 보는 것이 좋습니다.

testscenarios는 python unittest 스타일의 테스트를 위한 깨끗한 의존성 주입을 제공합니다.이는 인터페이스 테스트(단일 테스트 스위트를 통해 많은 구현을 테스트) 또는 클래식 의존성 주입(테스트 코드 자체에 대한 외부 의존성을 가진 테스트를 제공하여 다양한 상황에서 쉽게 테스트할 수 있음)에 사용할 수 있습니다.

퍼즈나 속성 기반 테스트를 추가하는 가설도 있습니다.

이것은 매우 강력한 테스트 방법입니다.

nose-itr 플러그인을 사용할 수 있습니다(pip install nose-ittr를 참조해 주세요.

기존 테스트와의 통합은 매우 간단하며 최소한의 변경(있는 경우)만 필요합니다.또한 노즈 멀티프로세싱 플러그인도 지원합니다.

, 커스터마이즈 할 .setup각 테스트마다 기능합니다.

@ittr(number=[1, 2, 3, 4])
def test_even(self):
    assert_equal(self.number % 2, 0)

요.nosetest attrib할 수

nosetest -a number=2

나는 메타클래스와 데코레이터를 사용하여 테스트를 수행합니다.구현 python_wrap_case를 확인하실 수 있습니다.이 라이브러리에는 테스트 프레임워크가 필요하지 않습니다.

예:

import unittest
from python_wrap_cases import wrap_case


@wrap_case
class TestSequence(unittest.TestCase):

    @wrap_case("foo", "a", "a")
    @wrap_case("bar", "a", "b")
    @wrap_case("lee", "b", "b")
    def testsample(self, name, a, b):
        print "test", name
        self.assertEqual(a, b)

콘솔 출력:

testsample_u'bar'_u'a'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test bar
FAIL
testsample_u'foo'_u'a'_u'a' (tests.example.test_stackoverflow.TestSequence) ... test foo
ok
testsample_u'lee'_u'b'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test lee
ok

발전기를 사용할 수도 있습니다.예를 들어 이 코드는 인수를 사용하여 가능한 모든 테스트 조합을 생성합니다.a__list ★★★★★★★★★★★★★★★★★」b__list

import unittest
from python_wrap_cases import wrap_case


@wrap_case
class TestSequence(unittest.TestCase):

    @wrap_case(a__list=["a", "b"], b__list=["a", "b"])
    def testsample(self, a, b):
        self.assertEqual(a, b)

콘솔 출력:

testsample_a(u'a')_b(u'a') (tests.example.test_stackoverflow.TestSequence) ... ok
testsample_a(u'a')_b(u'b') (tests.example.test_stackoverflow.TestSequence) ... FAIL
testsample_a(u'b')_b(u'a') (tests.example.test_stackoverflow.TestSequence) ... FAIL
testsample_a(u'b')_b(u'b') (tests.example.test_stackoverflow.TestSequence) ... ok

'비슷하게 하다'와 같은 것입니다.parameterized와 같이, ""에 합니다.unittest:

def sub_test(param_list):
    """Decorates a test case to run it as a set of subtests."""

    def decorator(f):

        @functools.wraps(f)
        def wrapped(self):
            for param in param_list:
                with self.subTest(**param):
                    f(self, **param)

        return wrapped

    return decorator

사용 예:

class TestStuff(unittest.TestCase):
    @sub_test([
        dict(arg1='a', arg2='b'),
        dict(arg1='x', arg2='y'),
    ])
    def test_stuff(self, arg1, arg2):
        ...

얼마 전 라돈의 소스 코드(GitHub 저장소에서의 사용 예)를 보고 ParamUnittest(파라미터 유니테스트)를 알게 되었습니다.TestCase를 확장하는 다른 프레임워크(Nose 등)와 연동해야 합니다.

다음은 예를 제시하겠습니다.

import unittest
import paramunittest


@paramunittest.parametrized(
    ('1', '2'),
    #(4, 3),    <---- Uncomment to have a failing test
    ('2', '3'),
    (('4', ), {'b': '5'}),
    ((), {'a': 5, 'b': 6}),
    {'a': 5, 'b': 6},
)
class TestBar(TestCase):
    def setParameters(self, a, b):
        self.a = a
        self.b = b

    def testLess(self):
        self.assertLess(self.a, self.b)
import unittest

def generator(test_class, a, b):
    def test(self):
        self.assertEqual(a, b)
    return test

def add_test_methods(test_class):
    # The first element of list is variable "a", then variable "b", then name of test case that will be used as suffix.
    test_list = [[2,3, 'one'], [5,5, 'two'], [0,0, 'three']]
    for case in test_list:
        test = generator(test_class, case[0], case[1])
        setattr(test_class, "test_%s" % case[2], test)


class TestAuto(unittest.TestCase):
    def setUp(self):
        print 'Setup'
        pass

    def tearDown(self):
        print 'TearDown'
        pass

_add_test_methods(TestAuto)  # It's better to start with underscore so it is not detected as a test itself

if __name__ == '__main__':
    unittest.main(verbosity=1)

결과:

>>>
Setup
FTearDown
Setup
TearDown
.Setup
TearDown
.
======================================================================
FAIL: test_one (__main__.TestAuto)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:/inchowar/Desktop/PyTrash/test_auto_3.py", line 5, in test
    self.assertEqual(a, b)
AssertionError: 2 != 3

----------------------------------------------------------------------
Ran 3 tests in 0.019s

FAILED (failures=1)

여기 보이는 메타클래스를 사용합니다.

class DocTestMeta(type):
    """
    Test functions are generated in metaclass due to the way some
    test loaders work. For example, setupClass() won't get called
    unless there are other existing test methods, and will also
    prevent unit test loader logic being called before the test
    methods have been defined.
    """
    def __init__(self, name, bases, attrs):
        super(DocTestMeta, self).__init__(name, bases, attrs)

    def __new__(cls, name, bases, attrs):
        def func(self):
            """Inner test method goes here"""
            self.assertTrue(1)

        func.__name__ = 'test_sample'
        attrs[func.__name__] = func
        return super(DocTestMeta, cls).__new__(cls, name, bases, attrs)

class ExampleTestCase(TestCase):
    """Our example test case, with no methods defined"""
    __metaclass__ = DocTestMeta

출력:

test_sample (ExampleTestCase) ... OK

나는 매우 특정한 스타일의 매개 변수화된 테스트에 어려움을 겪고 있었다.Selenium 테스트는 모두 로컬에서 실행할 수 있지만 Source Labs의 여러 플랫폼에 대해 원격으로 실행할 수도 있습니다.기본적으로 이미 작성된 테스트 케이스를 최대한 적게 변경하여 파라미터화하고 싶었습니다.게다가 파라미터를 setUp 메서드에 전달할 필요가 있었습니다.이것은 다른 솔루션에서는 볼 수 없었던 것입니다.

제가 생각해낸 것은 다음과 같습니다.

import inspect
import types

test_platforms = [
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "10.0"},
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "11.0"},
    {'browserName': "firefox", 'platform': "Linux", 'version': "43.0"},
]


def sauce_labs():
    def wrapper(cls):
        return test_on_platforms(cls)
    return wrapper


def test_on_platforms(base_class):
    for name, function in inspect.getmembers(base_class, inspect.isfunction):
        if name.startswith('test_'):
            for platform in test_platforms:
                new_name = '_'.join(list([name, ''.join(platform['browserName'].title().split()), platform['version']]))
                new_function = types.FunctionType(function.__code__, function.__globals__, new_name,
                                                  function.__defaults__, function.__closure__)
                setattr(new_function, 'platform', platform)
                setattr(base_class, new_name, new_function)
            delattr(base_class, name)

    return base_class

이를 위해 제가 해야 할 일은 각각의 일반적인 오래된 TestCase에 간단한 데코레이터 @sauce_labs()를 추가하는 것이었습니다.이것들을 실행할 때, 그것들은 포장되어 다시 쓰여지고 모든 테스트 메서드가 파라미터화 되어 이름이 변경됩니다.LoginTests.test_login(self)은 LoginTests.test_login_internet_explector_10.0(self), LoginTests.test_login_fox_43.0(self)으로 실행되며 각 파라미터가 있어 셀프플랫폼을 결정합니다.Source Labs로의 접속이 초기화되기 전에.

어쨌든, 저는 이것이 테스트의 유사한 "글로벌" 매개 변수화를 하려는 사람에게 도움이 되기를 바랍니다!

사용할 수 있습니다.TestSuite및 커스텀TestCase반.

import unittest

class CustomTest(unittest.TestCase):
    def __init__(self, name, a, b):
        super().__init__()
        self.name = name
        self.a = a
        self.b = b

    def runTest(self):
        print("test", self.name)
        self.assertEqual(self.a, self.b)

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(CustomTest("Foo", 1337, 1337))
    suite.addTest(CustomTest("Bar", 0xDEAD, 0xC0DE))
    unittest.TextTestRunner().run(suite)

특히 데이터 수집에 대해 약간 다른 프로세스를 수행하는 테스트를 생성해야 할 경우 이 테스트가 제 목적에 적합하다는 것을 알게 되었습니다.

import unittest

def rename(newName):
    def renamingFunc(func):
        func.__name__ == newName
        return func
    return renamingFunc

class TestGenerator(unittest.TestCase):

    TEST_DATA = {}

    @classmethod
    def generateTests(cls):
        for dataName, dataValue in TestGenerator.TEST_DATA:
            for func in cls.getTests(dataName, dataValue):
                setattr(cls, "test_{:s}_{:s}".format(func.__name__, dataName), func)

    @classmethod
    def getTests(cls):
        raise(NotImplementedError("This must be implemented"))

class TestCluster(TestGenerator):

    TEST_CASES = []

    @staticmethod
    def getTests(dataName, dataValue):

        def makeTest(case):

            @rename("{:s}".format(case["name"]))
            def test(self):
                # Do things with self, case, data
                pass

            return test

        return [makeTest(c) for c in TestCluster.TEST_CASES]

TestCluster.generateTests()

TestGenerator클래스는 다음과 같은 다양한 테스트 케이스를 생성하기 위해 사용될 수 있습니다.TestCluster.

TestCluster의 실장이라고 생각할 수 있다.TestGenerator인터페이스입니다.

이 솔루션은unittest그리고.nosePython 2 및 Python 3의 경우:

#!/usr/bin/env python
import unittest

def make_function(description, a, b):
    def ghost(self):
        self.assertEqual(a, b, description)
    print(description)
    ghost.__name__ = 'test_{0}'.format(description)
    return ghost


class TestsContainer(unittest.TestCase):
    pass

testsmap = {
    'foo': [1, 1],
    'bar': [1, 2],
    'baz': [5, 5]}

def generator():
    for name, params in testsmap.iteritems():
        test_func = make_function(name, params[0], params[1])
        setattr(TestsContainer, 'test_{0}'.format(name), test_func)

generator()

if __name__ == '__main__':
    unittest.main()

메타프로그래밍은 재미있지만 방해가 될 수 있어요.대부분의 솔루션에서는 다음 작업을 수행하는 것이 어렵습니다.

  • 선택적으로 테스트를 시작하다
  • 테스트명이 붙은 코드를 가리키다

따라서 첫 번째 제안사항은 단순/명시적 경로(모든 테스트 주자와 함께 작동)를 따르는 것입니다.

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

같은 말을 반복해서는 안 되기 때문에, 제 두 번째 제안은 하비에르의 대답에 기초하고 있습니다: 재산 기반 테스트를 수용하십시오.가설 라이브러리:

  • 테스트 케이스 생성에 대해 단순한 인간보다 더 가차없이 편파적이다.

  • 간단한 카운트 카운터를 제공합니다.

  • 모든 테스트 주자와 함께 작업

  • 에는 더 많은 흥미로운 기능(통계, 추가 테스트 출력 등)이 있습니다.

    클래스 Test Sequence(유니티스트).Test Case) :

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

구체적인 예를 테스트하려면 다음 항목을 추가하십시오.

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

특정 예제를 하나만 실행하려면 다른 예제를 주석으로 추가할 수 있습니다(예제가 먼저 실행됩니다).사용할 수 있습니다.@given(st.nothing())또 다른 옵션은 블록 전체를 다음과 같이 교체하는 것입니다.

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

좋아요, 당신은 뚜렷한 테스트 이름을 가지고 있지 않아요.하지만 필요한 건 다음과 같습니다.

  • 테스트 대상 자산의 설명적인 이름.
  • 이 입력은 실패로 이어집니다(예 확인).

더 재미있는 예

이 작업을 하는 데 어려움을 겪었습니다.setUpClass.

여기 하비에르의 대답 버전이 있습니다.setUpClass을 사용하다

import unittest


class GeneralTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print ''
        print cls.p1
        print cls.p2

    def runTest1(self):
        self.assertTrue((self.p2 - self.p1) == 1)

    def runTest2(self):
        self.assertFalse((self.p2 - self.p1) == 2)


def load_tests(loader, tests, pattern):
    test_cases = unittest.TestSuite()
    for p1, p2 in [(1, 2), (3, 4)]:
        clsname = 'TestCase_{}_{}'.format(p1, p2)
        dct = {
            'p1': p1,
            'p2': p2,
        }
        cls = type(clsname, (GeneralTestCase,), dct)
        test_cases.addTest(cls('runTest1'))
        test_cases.addTest(cls('runTest2'))
    return test_cases

출력

1
2
..
3
4
..
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

하지만 Python 3에서는 .__metaclass__Atribute를 metaclass 다음과 같습니다.

class ExampleTestCase(TestCase,metaclass=DocTestMeta):
    pass
import unittest

def generator(test_class, a, b,c,d,name):
    def test(self):
        print('Testexecution=',name)
        print('a=',a)
        print('b=',b)
        print('c=',c)
        print('d=',d)

    return test

def add_test_methods(test_class):
    test_list = [[3,3,5,6, 'one'], [5,5,8,9, 'two'], [0,0,5,6, 'three'],[0,0,2,3,'Four']]
    for case in test_list:
        print('case=',case[0], case[1],case[2],case[3],case[4])
        test = generator(test_class, case[0], case[1],case[2],case[3],case[4])
        setattr(test_class, "test_%s" % case[4], test)


class TestAuto(unittest.TestCase):
    def setUp(self):
        print ('Setup')
        pass

    def tearDown(self):
        print ('TearDown')
        pass

add_test_methods(TestAuto)

if __name__ == '__main__':
    unittest.main(verbosity=1)

다음은 저의 해결책입니다.다음과 같은 경우에 도움이 됩니다.

  1. 한 치의 오차도 없을 거야.테스트 케이스 및 단시간 검출

  2. 다른 파라미터 설정에 대해 일련의 테스트를 실행합니다.

  3. 매우 심플하고 다른 패키지에 의존하지 않음

     import unittest
    
     class BaseClass(unittest.TestCase):
         def setUp(self):
             self.param = 2
             self.base = 2
    
         def test_me(self):
             self.assertGreaterEqual(5, self.param+self.base)
    
         def test_me_too(self):
             self.assertLessEqual(3, self.param+self.base)
    
    
      class Child_One(BaseClass):
         def setUp(self):
             BaseClass.setUp(self)
             self.param = 4
    
    
      class Child_Two(BaseClass):
         def setUp(self):
             BaseClass.setUp(self)
             self.param = 1
    

setatr을 사용하는 것 외에 python 3.2 이후에서는 load_tests를 사용할 수 있습니다.

class Test(unittest.TestCase):
    pass

def _test(self, file_name):
    open(file_name, 'r') as f:
        self.assertEqual('test result',f.read())

def _generate_test(file_name):
    def test(self):
        _test(self, file_name)
    return test

def _generate_tests():
    for file in files:
        file_name = os.path.splitext(os.path.basename(file))[0]
        setattr(Test, 'test_%s' % file_name, _generate_test(file))

test_cases = (Test,)

def load_tests(loader, tests, pattern):
    _generate_tests()
    suite = TestSuite()
    for test_class in test_cases:
        tests = loader.loadTestsFromTestCase(test_class)
        suite.addTests(tests)
    return suite

if __name__ == '__main__':
    _generate_tests()
    unittest.main()

언급URL : https://stackoverflow.com/questions/32899/how-do-you-generate-dynamic-parameterized-unit-tests-in-python

반응형