Самое первое полученное вами сообщение об ошибке имеет смысл и многое объясняет.
print MyTestCase.suite # <unbound method MyTestCase.suite>
Вольный . Это означает, что вы не можете вызвать его, если не связываете его с экземпляром. Это на самом деле то же самое для MyTestCase.run
:
print MyTestCase.run # <unbound method MyTestCase.run>
Возможно, сейчас вы не понимаете, почему не можете позвонить suite
, но, пожалуйста, оставьте это в стороне. Вы бы попытались позвонить run
в классе, как указано выше? Что-то вроде:
MyTestCase.run() # ?
Наверное, нет, верно? Не имеет смысла писать это, и это не будет работать, потому что run
является методом экземпляра, и для работы требуется экземпляр self
. Похоже, что Python «понимает» suite
так же, как он понимает run
как несвязанный метод.
Посмотрим, почему:
Если вы попытаетесь вывести метод suite
из области видимости класса и определить его как глобальную функцию, он просто будет работать:
import unittest
def average(values):
return sum(values) / len(values)
class MyTestCase(unittest.TestCase):
def testFoo(self):
self.assertEqual(average([10,100]),55)
def testBar(self):
self.assertEqual(average([11]),11)
def testBaz(self):
self.assertEqual(average([20,20]),20)
def suite():
suite = unittest.TestSuite()
suite.addTest(MyTestCase('testFoo'))
suite.addTest(MyTestCase('testBar'))
suite.addTest(MyTestCase('testBaz'))
return suite
print suite() # <unittest.TestSuite tests=[<__main__.MyTestCase testMethod=testFoo>, <__main__.MyTestCase testMethod=testBar>, <__main__.MyTestCase testMethod=testBaz>]>
Но вы не хотите, чтобы это выходило за рамки класса, потому что вы хотите позвонить MyTestCase.suite()
Вы, вероятно, думали, что, поскольку suite
является своего рода "статическим" или независимым от экземпляра, не имеет смысла ставить аргумент self
, не так ли?
Это верно.
Но если вы определите метод внутри класса Python, Python будет ожидать, что этот метод будет иметь аргумент self
в качестве первого аргумента. Простое пропускание аргумента self
не делает ваш метод static
автоматически. Если вы хотите определить «статический» метод, вы должны использовать декоратор staticmethod :
@staticmethod
def suite():
suite = unittest.TestSuite()
suite.addTest(MyTestCase('testFoo'))
suite.addTest(MyTestCase('testBar'))
suite.addTest(MyTestCase('testBaz'))
return suite
Таким образом, Python рассматривает MyTestCase не как метод экземпляра, а как функцию:
print MyTestCase.suite # <function suite at 0x...>
И, конечно, теперь вы можете позвонить MyTestCase.suite()
, и это сработает, как и ожидалось.
if __name__ == '__main__':
s = MyTestCase.suite()
unittest.TextTestRunner().run(s) # Ran 3 tests in 0.000s, OK