Реактор останавливается между тестами при использовании twisted.trial.unittest - PullRequest
2 голосов
/ 20 января 2012

Есть ли способ поддерживать связь между тестами в режиме онлайн?

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

Чтобы изучить это, я подготовил пример тестового файла (ниже).

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

Пример:

#! /usr/bin/python
# -*- coding: utf-8 -*-

import logging

from twisted.python import log
from twisted.internet import defer, base, reactor
from twisted.trial import unittest
from twisted.internet.protocol import Protocol, Factory
from twisted.internet.endpoints import TCP4ServerEndpoint

observer = log.PythonLoggingObserver()
observer.start()
logging.basicConfig(level=logging.DEBUG)

class Echo(Protocol):
    '''Protocol from twistedmatrix examples'''
    def connectionMade(self):
        log.msg('Got incomming connection')
        self.transport.write("An apple a day keeps the doctor away\r\n")

    def connectionLost(self, reason):
        log.msg('Connection lost due to: %s' % reason)

    def dataReceived(self, data):
        self.transport.write(data)
        log.msg('Got some data: %s' % data)


class EchoFactory(Factory):
    '''Factory from twistedmatrix examples'''
    def buildProtocol(self, addr):
        return Echo()


class SampleTest(unittest.TestCase):
    '''Sample test case class derived straight from twisteds TestCase'''
    is_a_first_test = True
    endppoint = None
    def logLater(self, msgg = None):
        log.msg('called later message')

    @defer.inlineCallbacks
    def setUp(self):
        if self.__class__.is_a_first_test:
            self.__class__.endpoint = TCP4ServerEndpoint(reactor, 8007)
            self.__class__.endpoint.listen(EchoFactory())
            self.__class__.is_a_first_test = False

        log.msg('setting Up ... You may try (re)connecting now!!!')
        log.msg('We have endpoint: %s' % self.endpoint)
        yield reactor.callLater(5, self.logLater)
        log.msg('setUp done')

    def tearDown(self):
        log.msg('tearDown started')
        result = defer.Deferred()
        result.addCallback(self.logLater)
        reactor.callLater(5, result.callback, 'tearDown msg')
        log.msg('leaving tearDown')
        return result

    @defer.inlineCallbacks
    def test_00(self):
        log.msg('00 test body')
        sample_defer = defer.Deferred()
        sample_defer.addCallback(self.logLater)
        reactor.callLater(5, sample_defer.callback, 'Some sample action 00')
        log.msg('waiting reactor deferred')
        yield sample_defer
        log.msg('done with test body')

    @defer.inlineCallbacks
    def test_01(self):
        log.msg('01 test body')
        sample_defer = defer.Deferred()
        sample_defer.addCallback(self.logLater)
        reactor.callLater(5, sample_defer.callback, 'Some sample action 01')
        log.msg('waiting reactor deferred')
        yield sample_defer

    @defer.inlineCallbacks
    def test_02(self):
        log.msg('02 test body')
        sample_defer = defer.Deferred()
        sample_defer.addCallback(self.logLater)
        reactor.callLater(5, sample_defer.callback, 'Some sample action 02')
        log.msg('waiting reactor deferred')
        yield sample_defer

Запуск вышеуказанного файла с:

trial test-file.py

показывает «основной цикл завершен» в конце каждого теста. После этого порт остается прослушиваемым во всех тестах (согласно netstat -n4lt). Но при подключении через telnet во время 2-го и 3-го тестового корпуса эхо отсутствует (только для 1-го).

Витой документ http://twistedmatrix.com/documents/current/core/howto/testing.html#auto3 говорит: "Испытание запускает весь набор тестов (более четырех тысяч тестов) в одном процессе с одним реактором" (к сожалению, мой запрос на регистрацию в twistedmatrix все еще не подтвержден, поэтому я не могу разместить там вопросы).

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

Итак, есть ли способ поддерживать онлайн-соединение между тестами?

PS Использование Python 2.7.1, витой питон 10.2.0-1, Ubuntu 11.04

1 Ответ

2 голосов
/ 21 января 2012

Юнит-тесты должны быть изолированными и независимыми.Соединения, установленные в одном, не должны использоваться другим.

Глобальный реактор является неудачной частью общего изменяемого состояния.Модульные тесты должны по возможности избегать его использования.В качестве помощи изоляции и независимости, проба сбрасывает ее (насколько это возможно) между методами испытаний.Эту функцию нельзя отключить.

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

Ваши юнит-тесты могут использовать эту проверенную подделку, создавая новую для каждого метода тестирования.Это позволяет избежать проблем, связанных с нарушением изоляции и независимости, а также позволяет быстро запускать ваши модульные тесты.

...