2014-01-30 2 views
19

Как сохранить изменения, сделанные в пределах одного объекта, наследующего от TestCase в unitttest?Персистская переменная изменяется между тестами в unittest?

from unittest import TestCase, main as unittest_main 


class TestSimpleFoo(TestCase): 
    foo = 'bar' 

    def setUp(self): 
     pass 

    def test_a(self): 
     self.assertEqual(self.foo, 'bar') 
     self.foo = 'can' 

    def test_f(self): 
     self.assertEqual(self.foo, 'can') 


if __name__ == '__main__': 
    unittest_main() 

т.е .: Я хочу, чтобы эти два теста выше, чтобы пройти

+3

Единичные испытания должны быть независимыми. [В любом случае 'self.foo' ссылается на переменную * экземпляра *, тогда как' foo = 'bar'' (где она находится) присваивает переменную * class *.] – user2864740

+0

Я тестирую OAuth2; 'login' устанавливает' access_token', который требуется для следующих нескольких тестов. –

+1

Не можете ли вы создать * другой * тестовый класс с соответствующим 'setUp', чтобы высмеять соответствующий access_token? (Заставьте setUp вызывать OAuth по мере необходимости, больше тестирования интеграции на данный момент .. но считайте, что setUp * не может быть ошибочным *, или другой TestCase провалился.) – user2864740

ответ

28

Как некоторые комментарии эхом, структурирование ваших тестов таким образом, вероятно, является дефектом дизайна в самих тестах, и вы должны рассмотреть возможность их реструктуризации. Однако, если вы хотите сделать это и полагаться на то, что используемый вами тестовый бегун выполняет их в алфавитном порядке (по-видимому), я предлагаю следующее.

Похоже на то, что говорил @Matthias, но я бы сделал одну вещь по-разному в тех случаях, когда вы можете решить наследовать от класса на более поздний срок.

from unittest import TestCase, main as unittest_main 


class TestSimpleFoo(TestCase): 
    foo = 'bar' 

    def setUp(self): 
     pass 

    def test_a(self): 
     self.assertEqual(self.__class__.foo, 'bar') 
     self.__class__.foo = 'can' 

    def test_f(self): 
     self.assertEqual(self.__class__.foo, 'can') 


if __name__ == '__main__': 
    unittest_main() 

Разница между этим ответом и @ ответ Матиаса ты принял это явное объявление класса по сравнению с поиском указанной ссылки класса.

TestSimpleFoo vs self.__class__ 

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

+1

Да, я использовал весь синтаксис 'def test_0' для преодоления проблем сортировки. Конечно, будет использовать '__class__'; который также более краток =). Да, я мог бы реструктурировать свои тесты; но предпочтет более чистый интерфейс тестирования. –

0

не мог понять его; поэтому в конечном итоге взлома его с несколько не test_ префиксом функций:

def test_password_credentials_grant(self): 
    for user in self.user_mocks: 
     self.register(user) 
     self.login(user) 
     self.access_token(user, self.assertEqual) # Ensures access_token is generated+valid 
     self.logout(user) 
     self.access_token(user, self.assertNotEqual) # Ensures access_token is now invalid 
     self.unregister(user) 
+0

Это правильный способ сделать это. –

6

Мне нравится ваш собственный ответ для простоты, но если вы хотите сохранить различные модульные тесты:

Видимо UnitTest проходит отдельные тесты со свежими экземплярами TestCase. Ну, просто привяжите объекты к чему-то еще, кроме себя. Например:

from unittest import TestCase, main as unittest_main 


class TestSimpleFoo(TestCase): 

    def setUp(self): 
     pass 

    def test_a(self): 
     TestSimpleFoo.foo = 'can' 

    def test_f(self): 
     self.assertEqual(TestSimpleFoo.foo, 'can') 


if __name__ == '__main__': 
    unittest_main() 

Вы можете быть interesed в setUpClass и tearDownClass тоже: https://docs.python.org/3/library/unittest.html#setupclass-and-teardownclass

Также позаботьтесь о порядке выполнения ваших модульных тестов: https://docs.python.org/2/library/unittest.html#unittest.TestLoader.sortTestMethodsUsing

+0

Спасибо, я уже использую '@ tearDownClass' для моей' незарегистрированной' функции. Интересный подход, который вы предлагаете: даст ему уйти. –

+1

Вы не должны это делать.Что делать, если ваш тестовый бегун решает запустить тесты в отдельных процессах (например, распределяя нагрузку на несколько компьютеров)? Существуют определенные предположения, которые тестирующие участники делают об одном модульном тесте, и вы не должны их нарушать. Как говорит Нед, ответ «Т» - это правильный способ сделать это. –

+1

Мне не нравится это решение, это не обязательно, чтобы структурировать ваши тесты таким образом. Я считаю, что наиболее жизнеспособным решением является реструктуризация/проектирование ваших тестов, поэтому они согласуются с концептуальными идеями тестирования модулей python. – brunsgaard