У меня есть тестовый файл, содержащий тесты, занимающие довольно много времени (они отправляют вычисления в кластер и ждут результата). Все они относятся к определенному классу TestCase.
Поскольку они требуют времени и, кроме того, вряд ли будут разбиваться, я хочу, чтобы иметь возможность выбрать, выполняется ли это подмножество тестов или не выполняется (лучший способ был бы с аргументом командной строки, то есть "./tests.py --offline
" или что-то в этом роде), поэтому я мог запускать большую часть тестов часто и быстро, и весь набор время от времени, когда у меня есть время.
В настоящее время я просто использую unittest.main()
для запуска тестов.
Спасибо.
Ответ 1
По умолчанию unittest.main()
использует тестовый загрузчик по умолчанию, чтобы вывести TestSuite из модуля, в котором работает main.
Вам не нужно использовать это поведение по умолчанию.
Вы можете, например, сделать три экземпляра unittest.TestSuite.
-
"Быстрое" подмножество.
fast = TestSuite()
fast.addTests( TestFastThis )
fast.addTests( TestFastThat )
-
Подменю "slow".
slow = TestSuite()
slow.addTests( TestSlowAnother )
slow.addTests( TestSlowSomeMore )
-
"Целый" набор.
alltests = unittest.TestSuite([fast, slow])
Обратите внимание, что я скорректировал имена TestCase, чтобы указать Fast vs. Slow. Вы можете подклассы
unittest.TestLoader для анализа имен классов и создания нескольких загрузчиков.
Затем ваша основная программа может анализировать аргументы командной строки с помощью optparse или argparse (доступно с 2.7 или 3.2), чтобы выбрать, какой пакет вы хотите запустить, быстро, медленно или все.
Или вы можете доверять, что sys.argv[1]
является одним из трех значений и использует что-то простое, чем это
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
Ответ 2
Чтобы запустить только один конкретный тест, вы можете использовать:
$ python -m unittest test_module.TestClass.test_method
Подробнее здесь
Ответ 3
Собственно, имена тестового примера можно передать как sys.argv, и будут проверены только те случаи.
Например, предположим, что у вас
class TestAccount(unittest.TestCase):
...
class TestCustomer(unittest.TestCase):
...
class TestShipping(unittest.TestCase):
...
account = TestAccount
customer = TestCustomer
shipping = TestShipping
Вы можете позвонить
python test.py account
чтобы иметь только тесты учетной записи или даже
$ python test.py account customer
для проверки обоих случаев
Ответ 4
У вас есть в основном два способа сделать это:
- Определите свой собственный набор тестов для класса
- Создайте классные классы соединения кластера, которые возвратят фактические данные.
Я - сильный сторонник его второго подхода; a unit test должен тестировать только очень единицу кода, а не сложные системы (например, базы данных или кластеры). Но я понимаю, что это не всегда возможно; иногда создание макетов просто слишком дорого, или цель теста действительно находится в сложной системе.
Возвращаясь к опции (1), вы можете действовать следующим образом:
suite = unittest.TestSuite()
suite.addTest(MyUnitTestClass('quickRunningTest'))
suite.addTest(MyUnitTestClass('otherTest'))
а затем передать пакет тестируемому бегуну:
unittest.TextTestRunner().run(suite)
Дополнительная информация о документации python: http://docs.python.org/library/unittest.html#testsuite-objects
Ответ 5
Поскольку вы используете unittest.main()
, вы можете просто запустить python tests.py --help
, чтобы получить документацию:
Usage: tests.py [options] [test] [...]
Options:
-h, --help Show this message
-v, --verbose Verbose output
-q, --quiet Minimal output
-f, --failfast Stop on first failure
-c, --catch Catch control-C and display results
-b, --buffer Buffer stdout and stderr during test runs
Examples:
tests.py - run default set of tests
tests.py MyTestSuite - run suite 'MyTestSuite'
tests.py MyTestCase.testSomething - run MyTestCase.testSomething
tests.py MyTestCase - run all 'test*' test methods
in MyTestCase
То есть, вы можете просто сделать
python tests.py TestClass.test_method
Ответ 6
Я делаю это, используя простой skipIf
:
import os
SLOW_TESTS = int(os.getenv('SLOW_TESTS', '0'))
@unittest.skipIf(not SLOW_TESTS, "slow")
class CheckMyFeature(unittest.TestCase):
def runTest(self):
…
Таким образом, мне нужно только украсить уже существующий тестовый пример этой отдельной строкой (нет необходимости создавать тестовые пакеты или аналогичные, только одну строку вызова os.getenv()
в начале моего файла unit test) и как по умолчанию этот тест пропускается.
Если я хочу выполнить его, несмотря на медленность, я просто вызываю свой script следующим образом:
SLOW_TESTS=1 python -m unittest …
Ответ 7
Или вы можете использовать функцию unittest.SkipTest()
. Например, добавьте метод skipOrRunTest
в ваш тестовый класс следующим образом:
def skipOrRunTest(self,testType):
#testsToRun = 'ALL'
#testsToRun = 'testType1, testType2, testType3, testType4,...etc'
#testsToRun = 'testType1'
#testsToRun = 'testType2'
#testsToRun = 'testType3'
testsToRun = 'testType4'
if ((testsToRun == 'ALL') or (testType in testsToRun)):
return True
else:
print "SKIPPED TEST because:\n\t testSuite '" + testType + "' NOT IN testsToRun['" + testsToRun + "']"
self.skipTest("skipppy!!!")
Затем добавьте вызов этого метода skipOrRunTest к самому началу каждого из ваших модульных тестов следующим образом:
def testType4(self):
self.skipOrRunTest('testType4')
Ответ 8
Посмотрите на использование выделенного testrunner, например py.test, носа или, возможно, даже zope.testing. Все они имеют параметры командной строки для выбора тестов.
Посмотрите, например, как нос: https://pypi.python.org/pypi/nose/1.3.0
Ответ 9
Я попробовал ответить @slott:
if __name__ == "__main__":
suite = eval(sys.argv[1]) # Be careful with this line!
unittest.TextTestRunner().run(suite)
Но это дало мне следующую ошибку:
Traceback (most recent call last):
File "functional_tests.py", line 178, in <module>
unittest.TextTestRunner().run(suite)
File "/usr/lib/python2.7/unittest/runner.py", line 151, in run
test(result)
File "/usr/lib/python2.7/unittest/case.py", line 188, in __init__
testMethod = getattr(self, methodName)
TypeError: getattr(): attribute name must be string
Следующие работали для меня:
if __name__ == "__main__":
test_class = eval(sys.argv[1])
suite = unittest.TestLoader().loadTestsFromTestCase(test_class)
unittest.TextTestRunner().run(suite)
Ответ 10
Я нашел другой способ выбрать методы test_ *, которые я только хочу запустить, добавив к ним атрибут. В основном вы используете метакласс для украшения вызываемых объектов внутри класса TestCase, у которых есть атрибут StepDebug с помощью декодера unittest.skip. Дополнительная информация о
Пропуск всех модульных тестов, но один в Python с помощью декораторов и метаклассов
Я не знаю, является ли это лучшим решением, чем выше. Я просто предоставляю его как вариант.
Ответ 11
Не удалось найти хороший способ сделать это раньше, поэтому поделитесь здесь.
Цель: собрать набор тестовых файлов, чтобы они могли работать как единое целое,
но мы все равно можем выбрать любой из них для самостоятельной работы.
Проблема: метод обнаружения не позволяет легко выбрать один тестовый пример для запуска.
Дизайн: см. ниже. Это выравнивает пространство имен, поэтому его можно выбрать по имени класса TestCase и оставить префикс "tests1.test_core":
./run-tests TestCore.test_fmap
код
test_module_names = [
'tests1.test_core',
'tests2.test_other',
'tests3.test_foo',
]
loader = unittest.defaultTestLoader
if args:
alltests = unittest.TestSuite()
for a in args:
for m in test_module_names:
try:
alltests.addTest( loader.loadTestsFromName( m+'.'+a ) )
except AttributeError as e:
continue
else:
alltests = loader.loadTestsFromNames( test_module_names )
runner = unittest.TextTestRunner( verbosity = opt.verbose )
runner.run( alltests )
Ответ 12
Это единственное, что сработало для меня.
if __name__ == '__main__':
unittest.main( argv=sys.argv, testRunner = unittest.TextTestRunner(verbosity=2))
Когда я это вызвал, мне пришлось передать имя класса и тестового имени. Немного неудобно, так как у меня нет запоминания имени класса и теста.
python./tests.py class_Name.test_30311
Удаление имени класса и имени теста выполняет все тесты в вашем файле. Я считаю, что это намного проще справиться с встроенным методом, поскольку я не изменяю свою команду в CLI. Просто добавьте параметр.
Enjoy,
Кит