Как я кратко реализую несколько подобных модульных тестов в Python unittest платформа?

 SELECT IIF(CalculationMethod = x and Price * coefficient < Amount, Amount, Price * coefficient) as CalculatedAmount 
      FROM aTable
15
задан Rajkumar S 31 October 2011 в 07:09
поделиться

7 ответов

Вы могли использовать метакласс для динамичной вставки тестов. Это хорошо работает для меня:

import unittest

class UnderTest(object):

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

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

class TestMeta(type):

    def __new__(cls, name, bases, attrs):
        funcs = [t for t in dir(UnderTest) if t[0] == 'f']

        def doTest(t):
            def f(slf):
                ut=UnderTest()
                getattr(ut, t)(3)
            return f

        for f in funcs:
            attrs['test_gen_' + f] = doTest(f)
        return type.__new__(cls, name, bases, attrs)

class T(unittest.TestCase):

    __metaclass__ = TestMeta

    def testOne(self):
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.main()
4
ответ дан 1 December 2019 в 02:10
поделиться

Вот мой любимый подход к "семейству связанных тестов". Мне нравятся явные подклассы TestCase, который выражает типичные функции.

class MyTestF1( unittest.TestCase ):
    theFunction= staticmethod( f1 )
    def setUp(self):
        self.matrix1 = numpy.ones((5,10))
        self.matrix2 = numpy.identity(5)
    def testOutputShape( self ):
        """Output of functions be of a certain shape"""
        output = self.theFunction(self.matrix1, self.matrix2)
        fail_message = "%s produces output of the wrong shape" % (self.theFunction.__name__,)
        self.assertEqual(self.matrix1.shape, output.shape, fail_message)

class TestF2( MyTestF1 ):
    """Includes ALL of TestF1 tests, plus a new test."""
    theFunction= staticmethod( f2 )
    def testUniqueFeature( self ):
         # blah blah blah
         pass

class TestF3( MyTestF1 ):
    """Includes ALL of TestF1 tests with no additional code."""
    theFunction= staticmethod( f3 )

Добавьте функцию, добавьте подкласс MyTestF1. Каждый подкласс MyTestF1 включает все тесты в MyTestF1 без дублированного кода любого вида.

Уникальные функции обрабатываются очевидным способом. Новые методы добавляются к подклассу.

Это абсолютно совместимо с unittest.main()

11
ответ дан 1 December 2019 в 02:10
поделиться

Если Вы уже используете нос (и некоторые Ваши комментарии предполагают, что Вы), почему не делают Вас, просто используют Тестовые Генераторы, которые являются самым простым способом реализовать параметрические тесты, с которыми я столкнулся:

Например:

from binary_search import search1 as search

def test_binary_search():
    data = (
        (-1, 3, []),
        (-1, 3, [1]),
        (0,  1, [1]),
        (0,  1, [1, 3, 5]),
        (1,  3, [1, 3, 5]),
        (2,  5, [1, 3, 5]),
        (-1, 0, [1, 3, 5]),
        (-1, 2, [1, 3, 5]),
        (-1, 4, [1, 3, 5]),
        (-1, 6, [1, 3, 5]),
        (0,  1, [1, 3, 5, 7]),
        (1,  3, [1, 3, 5, 7]),
        (2,  5, [1, 3, 5, 7]),
        (3,  7, [1, 3, 5, 7]),
        (-1, 0, [1, 3, 5, 7]),
        (-1, 2, [1, 3, 5, 7]),
        (-1, 4, [1, 3, 5, 7]),
        (-1, 6, [1, 3, 5, 7]),
        (-1, 8, [1, 3, 5, 7]),
    )

    for result, n, ns in data:
        yield check_binary_search, result, n, ns

def check_binary_search(expected, n, ns):
    actual = search(n, ns)
    assert expected == actual

Производит:

$ nosetests -d
...................
----------------------------------------------------------------------
Ran 19 tests in 0.009s

OK
5
ответ дан 1 December 2019 в 02:10
поделиться

Метаклассы являются одной опцией. Другая опция состоит в том, чтобы использовать a TestSuite:

import unittest
import numpy
import funcs

# get references to functions
# only the functions and if their names start with "matrixOp"
functions_to_test = [v for k,v in funcs.__dict__ if v.func_name.startswith('matrixOp')]

# suplly an optional setup function
def setUp(self):
    self.matrix1 = numpy.ones((5,10))
    self.matrix2 = numpy.identity(5)

# create tests from functions directly and store those TestCases in a TestSuite
test_suite = unittest.TestSuite([unittest.FunctionTestCase(f, setUp=setUp) for f in functions_to_test])


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

Не протестировали. Но это должно хорошо работать.

1
ответ дан 1 December 2019 в 02:10
поделиться

Проблема с этим подходом состоит в том, что, если какой-либо элемент списка проваливает тест, более поздние элементы не становятся протестированными.

При рассмотрении его с точки зрения, что, если тест перестал работать, который очень важен и весь пакет недопустим, то не имеет значения, что другие элементы не будут протестированы, потому что 'эй, у Вас есть ошибка зафиксировать'.

После того как тот тест передает, другие тесты будут затем работать.

По общему признанию существует информация, которая будет получена от знания, которого перестали работать другие тесты, и это может помочь с отладкой, но кроме этого, предположить, что любой отказ при испытании является отказом целого приложения.

-1
ответ дан 1 December 2019 в 02:10
поделиться

Приведенный выше код метакласса имеет проблемы с носом, потому что носовой параметр wantMethod в его selector.py смотрит на __ name __ данного метода тестирования, а не на ключ атрибута dict.

Чтобы использовать метод тестирования, определенный метаклассом, с носом, имя метода и ключ словаря должны быть одинаковыми и иметь префикс для обнаружения с помощью носа (то есть с помощью 'test _').

# test class that uses a metaclass
class TCType(type):
    def __new__(cls, name, bases, dct):
        def generate_test_method():
            def test_method(self):
                pass
            return test_method

        dct['test_method'] = generate_test_method()
        return type.__new__(cls, name, bases, dct)

class TestMetaclassed(object):
    __metaclass__ = TCType

    def test_one(self):
        pass
    def test_two(self):
        pass
1
ответ дан 1 December 2019 в 02:10
поделиться

Здесь вам не нужно использовать Мета-классы. Простой цикл отлично подходит. Взгляните на пример ниже:

import unittest
class TestCase1(unittest.TestCase):
    def check_something(self, param1):
        self.assertTrue(param1)

def _add_test(name, param1):
    def test_method(self):
        self.check_something(param1)
    setattr(TestCase1, 'test_'+name, test_method)
    test_method.__name__ = 'test_'+name

for i in range(0, 3):
    _add_test(str(i), False)

После выполнения for в TestCase1 есть 3 метода тестирования, которые поддерживаются как носом, так и юниттестом.

.
6
ответ дан 1 December 2019 в 02:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: