Ответ 1
Проблема, с которой вы столкнулись, заключается в том, что Nose определяет, включать или нет метод в набор тестов для запуска, просматривая имя, записанное в самой функции, а не атрибут, предоставляющий доступ к этой функции. Если я переименую ваши passer
и failer
в test_pass
и test_fail
, то Nose сможет найти тесты. Поэтому сами функции должны быть названы таким образом, чтобы они соответствовали тому, что дано -m
(или по умолчанию).
Здесь измененный код, который дает ожидаемые результаты:
from django.test import TestCase
from sys import modules
current_module = modules[__name__]
def test_pass(self, *args, **kw):
self.assertEqual(1, 1)
def test_fail(self, *args, **kw):
self.assertEqual(1, 2)
# Create a hundred ...
for i in xrange(100):
# ... of a stupid TestCase class that has 1 method that passes if `i` is
# even and fails if `i` is odd
klass_name = "Test_%s" % i
if i % 2: # Test passes if even
klass_attrs = {
'test_something_%s' % i: test_pass
}
else: # Fail if odd
klass_attrs = {
'test_something_%s' % i: test_fail
}
klass = type(klass_name, (TestCase,), klass_attrs)
# Set the class as "child" of the current module so that django test runner
# finds it
setattr(current_module, klass_name, klass)
# This prevents Nose from seeing them as tests after the loop is over.
test_pass = None
test_fail = None
Без двух последних назначений None
, Nose рассмотрит две функции верхнего уровня, которые будут модульными, и будут запускать их в дополнение к испытаниям в классах.
Другой способ получить те же результаты - определить __test__
для двух ваших функций:
def passer(self, *args, **kw):
self.assertEqual(1, 1)
passer.__test__ = 1
def failer(self, *args, **kw):
self.assertEqual(1, 2)
failer.__test__ = 1
И в конце файла:
# This prevents Nose from seeing them as tests after the loop is over.
passer = None
failer = None
Нос ищет наличие этих функций и если присутствует и задано значение, считается истинным, он будет использовать эту функцию в качестве тестового примера.
Логику, определяющую выбор методов, можно найти в файле Nose selector.py
в wantMethod
:
def wantMethod(self, method):
"""Is the method a test method?
"""
try:
method_name = method.__name__
except AttributeError:
# not a method
return False
if method_name.startswith('_'):
# never collect 'private' methods
return False
declared = getattr(method, '__test__', None)
if declared is not None:
wanted = declared
else:
wanted = self.matches(method_name)
plug_wants = self.plugins.wantMethod(method)
if plug_wants is not None:
wanted = plug_wants
log.debug("wantMethod %s? %s", method, wanted)
return wanted
Я не вижу ясного способа использовать -m
для запуска только некоторых тестов так, как вы этого хотите. Проблема в том, что -m
одинаково совпадает с именами файлов, директив, модулей, классов и функций. Если вы установите что-то вроде -m0$
, тогда все отдельные части, которые я только что привел, должны соответствовать регулярному выражению для выбранного теста. (Нос не объединяет их, а затем сопоставляется по комбинации.) Можно индивидуально перечислить тесты в командной строке, но это плохой заменитель регулярного выражения.