2012-01-20 47 views
2

有沒有一種方法可以在測試之間保持連接在線?使用twisted.trial.unittest時測試站之間會停止測試

我試圖讓用戶在運行多個測試集時保持記錄,但注意到意外的行爲:每次測試後反應器都會停止(所以一旦建立的連接變得不可用)。

爲了探索這個,我準備了示例測試文件(如下)。

這創建了簡單的偵聽回聲服務器並將其存儲在類字段中。 運行3個測試。 服務器預計在所有測試過程中都能正常運行(實際上它只在第一次測試結束時才運行)。

實施例:

#! /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連接在第二和第三個測試主體(僅針對第一個測試主體)時沒有回顯。

扭曲DOC http://twistedmatrix.com/documents/current/core/howto/testing.html#auto3說: 「試運行在一個單一的過程中,整個測試套件(四千測試),以單一反應器」 (不幸的是我twistedmatrix註冊請求仍然沒有驗證,因此無法在那裏提問)。

在我的真實情況下,與服務器的連接需要很長時間才能重複進行每次測試,所以我希望爲每類病例至少進行一次這樣的操作。

那麼,有沒有辦法在測試之間保持連接在線?

PS使用 蟒2.7.1, 蟒捻10.2.0-1, Ubuntu的11.04

回答

2

單元測試是爲了進行分離和獨立的。在另一箇中設置的連接不應該被使用。

全局反應堆是一個不幸的共享可變狀態。在可能的情況下,單元測試應該完全避免使用它。作爲孤立和獨立的輔助手段,審判會在測試方法之間重新設置它(儘可能多)。此功能無法禁用。

由於您的連接設置昂貴,因此您應該調查爲該連接創建驗證僞造。經過驗證的僞造是一些API的替代實現,它通常是更適合測試的(例如,創建僞造應該是快速的),並且擁有自己的單元測試集合,證明它的行爲與實際執行方式相同。

您的單元測試可以使用這個驗證的僞造,爲每個測試方法創建一個新的僞造。這樣可以避免違反隔離和獨立性的問題,還可以讓您的單元測試快速運行。

+0

因此,如果我做得對,重置反應堆是一種預期的行爲。 雖然我的測試客戶機/服務器也是基於雙絞線的(因此取決於單元測試所用的同一個電抗器),但雙絞線總是會嘗試重置其連接。 _問題:_扭曲目前不允許/鼓勵在測試套件(或其他類級別的動作,如setUpClass)中的測試之間分配和共享連接,並且這是一個有意識的決定,將來要轉向安全和嚴格的測試分離。 _是否正確?_ – yan

+0

這是正確的。 :)最終可能有多個反應堆,然後測試可能會共享一個與一個試驗所用反應堆不同的連接(然後這樣的連接只會是更多的狀態,試驗不知道並且無法控制)。 –