코가 동적으로 생성 된 테스트 케이스를 발견하게하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/347574

  •  19-08-2019
  •  | 
  •  

문제

이것은 a에 대한 후속 조치입니다 이전 질문 내.

이전 질문에서, 전체 기능 가족에 비해 본질적으로 동일한 테스트를 구현하는 방법을 탐색하여 실패한 첫 번째 기능에서 테스트가 중단되지 않도록합니다.

내가 선호하는 솔루션은 메타 클래스를 사용하여 테스트를 UnitTest.testcase에 동적으로 삽입했습니다. 불행히도 코는 코가 테스트 케이스를 정적으로 스캔하기 때문에 코는이를 선택하지 않습니다.

코가 어떻게 테스트 케이스를 발견하고 실행하도록하려면 어떻게해야합니까? 참조하시기 바랍니다 여기 문제의 테스트 케이스의 예는.

도움이 되었습니까?

해결책

코에는 이와 같은 것들을위한 "테스트 생성기"기능이 있습니다. Args와 함께 실행하려는 각 "테스트 케이스"기능을 생성하는 발전기 기능을 작성합니다. 이전 예제에 따라 별도의 테스트에서 각 기능을 확인할 수 있습니다.

import unittest
import numpy

from somewhere import the_functions

def test_matrix_functions():
    for function in the_functions:
        yield check_matrix_function, function

def check_matrix_function(function)
    matrix1 = numpy.ones((5,10))
    matrix2 = numpy.identity(5)
    output = function(matrix1, matrix2)
    assert matrix1.shape == output.shape, \
           "%s produces output of the wrong shape" % str(function)

다른 팁

코는 정적으로 테스트를 스캔하지 않으므로 ~할 수 있다 메타 클래스 마법을 사용하여 코가 찾은 테스트를합니다.

어려운 부분은 표준 메타 클래스 기술이 func_name 속성을 올바르게 설정하지 않는다는 것입니다. 이는 클래스의 메소드가 테스트인지 확인할 때 코가 찾는 것입니다.

간단한 메타 클래스가 있습니다. 그것은 func dict를 통해보고 그것을 찾은 모든 방법에 대한 새로운 메소드를 추가하여 발견 된 방법에 docstring이 있다고 주장합니다. 이 새로운 합성 방법에는 이름이 부여됩니다 "test_%d" %i.

import new
from inspect import isfunction, getdoc

class Meta(type):
    def __new__(cls, name, bases, dct):

        newdct = dct.copy()
        for i, (k, v) in enumerate(filter(lambda e: isfunction(e[1]), dct.items())):
            def m(self, func):
                assert getdoc(func) is not None

            fname = 'test_%d' % i
            newdct[fname] = new.function(m.func_code, globals(), fname,
                (v,), m.func_closure)

        return super(Meta, cls).__new__(cls, 'Test_'+name, bases, newdct)

이제이 메타 클라스를 사용하는 새로운 클래스를 만들어 봅시다.

class Foo(object):
    __metaclass__ = Meta

    def greeter(self):
        "sdf"
        print 'Hello World'

    def greeter_no_docstring(self):
        pass

런타임에 Foo 실제로 이름이 지정됩니다 Test_Foo 그리고 가질 것입니다 greeter, greeter_no_docstring, test_1 그리고 test_2 그 방법으로. 내가 달릴 때 nosetests 이 파일에는 다음은 출력입니다.

$ nosetests -v test.py
test.Test_Foo.test_0 ... FAIL
test.Test_Foo.test_1 ... ok

======================================================================
FAIL: test.Test_Foo.test_0
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/rmcgibbo/Desktop/test.py", line 10, in m
    assert getdoc(func) is not None
AssertionError

----------------------------------------------------------------------
Ran 2 tests in 0.002s

FAILED (failures=1)

이 메타 클라스는 그대로 유용하지 않지만 대신 사용하는 경우 Meta 적절한 메타 클라스가 아니라 기능적 메타 클라스 (즉, 클래스를 인수로 받아들이고 새로운 클래스를 반환합니다. ~이다 유용한. 이 접근법을 사용하여 Docstrings가 코 테스트 스위트의 일부로 Numpy 표준에 부착되도록 자동 테스트했습니다.

또한 New.Function과 함께 작동하는 적절한 폐쇄를 얻는 데 많은 어려움이 있었기 때문에이 코드가 사용하는 이유입니다. m(self, func) 어디 func 기본 인수로 만들어졌습니다. 폐쇄를 사용하는 것이 더 자연 스러울 것입니다. value, 그러나 그것은 작동하지 않는 것 같습니다.

type ()로 테스트 케이스 클래스를 생성 할 수 있습니다.

class UnderTest_MixIn(object):

    def f1(self, i):
        return i + 1

    def f2(self, i):
        return i + 2

SomeDynamicTestcase = type(
    "SomeDynamicTestcase", 
    (UnderTest_MixIn, unittest.TestCase), 
    {"even_more_dynamic":"attributes .."}
)

# or even:

name = 'SomeDynamicTestcase'
globals()[name] = type(
    name, 
    (UnderTest_MixIn, unittest.TestCase), 
    {"even_more_dynamic":"attributes .."}
)

코가 test_module을 가져 오려고 시도 할 때 생성되어야합니다.

이 접근법의 장점은 많은 테스트 조합을 동적으로 만들 수 있다는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top