Модульное тестирование Python с носом: создание последовательных тестов

Я только учусь проводить модульное тестирование. Я на Python/нос/Wing IDE.

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

Дело в том, что я хочу, чтобы некоторые из моих тестов использовали результаты моделирования, созданные в других тестах. Например, synchronous_test вычисляет некую симуляцию в синхронном режиме, но затем я хочу рассчитать ее в асинхронном режиме и проверить, что результаты вышли одинаковыми.

Как мне это структурировать? Поместить их все в одну тестовую функцию или сделать отдельную asynchronous_test? Передаю ли я эти объекты из одной тестовой функции в другую?

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


person Ram Rachum    schedule 27.03.2010    source источник
comment
Не могли бы вы указать какой-то конкретный класс, который вы хотите протестировать?   -  person Juho Vepsäläinen    schedule 27.03.2010
comment
bebraw, я не понимаю вашего вопроса. Я хочу протестировать функции simulate и list_simulate, класс Project и другие вещи.   -  person Ram Rachum    schedule 27.03.2010
comment
Хорошо. Учитывая, что проект с открытым исходным кодом, я подумал, что было бы интересно прочитать реальный код. :)   -  person Juho Vepsäläinen    schedule 28.03.2010


Ответы (2)


Вы можете добавить тесты, которые необходимо вычислить один раз для каждого класса, в «настройку» этого класса. Например:

from nose.tools import *
class Test_mysim():
    def setup(self):
        self.ans = calculate_it_once()

    def test_sync(self):
        ans=calculate_it_sync()
        assert_equal(ans,self.ans)

    def test_async(self):
        ans=calculate_it_async()
        assert_equal(ans,self.ans)
person Gregg Lind    schedule 27.03.2010
comment
И что происходит, когда calculate_it_once() терпит неудачу? - person Ram Rachum; 28.03.2010
comment
Я предположил, что вы знаете «ответ» (возможно, с помощью random.setseed() или чего-то еще). Если нет, то лучшее, что вы можете сделать, это утверждать, что синхронизация и асинхронность — это одно и то же, и это является проверкой. Я разветвил ваш код, но у меня не было возможности его посмотреть. - person Gregg Lind; 29.03.2010

В общем, я бы рекомендовал не заставлять один тест зависеть от другого. Выполните synchronous_test, выполните asynchronous_test, сравните их каждый с ожидаемым правильным выводом, а не друг с другом.

Итак, что-то вроде:

class TestSimulate(TestCase):
    def setup(self):
        self.simpack = SimpackToTest()
        self.initial_state = pickle.load("initial.state")
        self.expected_state = pickle.load("known_good.state")

    def test_simulate(self):
        state = simulate(self.simpack, self.initial_state)
        # assert_equal will require State to implement __eq__ in a meaningful
        # way.  If it doesn't, you'll want to define your own comparison 
        # function.
        self.assert_equal(self.expected_state, state)

    def test_other_simulate(self):
        foo = OtherThing(self.simpack)
        blah = foo.simulate(self.initial_state)
        state = blah.state
        self.assert_equal(self.expected_state, state)
person keturn    schedule 27.03.2010
comment
Итак, где мне рассчитать ожидаемый правильный результат? Потому что вычисление этого вывода — это то, что нужно проверить само по себе. - person Ram Rachum; 27.03.2010
comment
И как вы проверяете это? Сравнить его с... самим собой? Вы должны где-то знать хороший результат. Загрузить его из рассола? (ответ обновлен кодом) - person keturn; 28.03.2010
comment
Я думаю, вы правы. Хотя я не буду загружать из рассола-- Недостаточно просто вносить изменения таким образом. Я думаю, что я рассмотрю возможность сделать это, как в примере Грегга Линда. Вопрос: как вы думаете, это плохо, если я просто помещу много тестов в одну непрерывную функцию? Тогда мне не придется беспокоиться об этих вещах, и если что-то пойдет не так, мне все равно придется это исправить. - person Ram Rachum; 28.03.2010
comment
Небольшие функции в тестах или другом коде обычно облегчают отслеживание того, что происходит. И по мере того, как вы будете получать больше тестов, вы оцените способность инструмента тестирования точно сообщать вам, какие тесты не пройдены, а какие продолжают работать, когда вы что-то меняете. - person keturn; 28.03.2010
comment
кроме того, наличие структуры setup для обеспечения согласованных состояний и simpacks для ваших различных тестов кажется здесь полезным. - person keturn; 28.03.2010
comment
Мое решение и это решение очень похожи, что говорит о том, что мы оба в одном и том же меме. Если вам нужно проверить фактический ответ, то вам нужно где-то иметь этот ответ, либо в коде, в файле json (или pickle), либо вычислять с использованием заведомо хорошего (возможно, наивного и медленного) алгоритма. Вы должны сделать стенд где-то. - person Gregg Lind; 29.03.2010