Dream Test Framework. Log viewer tests (Часть 2)


(Mykhailo Poliarush) #1

Предыдущая часть

А пишите ли Вы тесты к Вашим тестам?

Масло маслянное :-)

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

Давайте напишем тесты!

С одной стороны это:

  • повышает надёжность самой тестовой системы
  • заставляет писать код лучше
  • и просто, круто!

С другой стороны:

  • несколько избыточно
  • требует времени

До этого эксперимента к идеи написания тестов к тестовому фреймворку я относился скептически. А сейчас (после их написания) мне эта идея всё больше нравится... Это заставило меня довольно сильно изменить изначальный код - в лучшую сторону.

Итак, будем использовать стандартный unittest для Питона.

Самый простой способ запуска - через CLI:

{syntaxhighlighter brush: bash;light: true; fontsize: 100; first-line: 1; }python testLogViewer.py{/syntaxhighlighter}

При этом результаты будут выходить в таком виде:

{syntaxhighlighter brush: bash;light: true; fontsize: 100; first-line: 1; }yuriy@yuriys:/warehouse/projects/dreamFramework/src/logViewer/test$ python testLogViewer.py
.........
----------------------------------------------------------------------
Ran 9 tests in 41.646s{/syntaxhighlighter}


А реализовано всё это так:

1. Есть один файл, в котором собраны все тесты - testLogViewer.py:

Для каждой однотипной группы тестов создаётся класс с набором тестовых методов. Например:

{syntaxhighlighter brush: python;light: true; fontsize: 100; first-line: 1; }class TestLogViewerBase(LogViewerTestBase):
""" """
def testSimple(self):
""" """
testString = "bla bla ERROR du du du"

    # emulate entering some data to log file
    self._addString(testString)

    # lets give some time for logViewer to wake up and check data
    time.sleep(timeforWaitingLogwatcher)

    # get captured data
    logMessagesForCurrentTestAndFile = self.getLogMessagesForCurrentTest()

    # assert captured data
    if logMessagesForCurrentTestAndFile.has_key(self._tagNames):
        logMessages = logMessagesForCurrentTestAndFile[self._tagNames]
        if logMessages and (1 == len(logMessages)):
            self.assertTrue(testString == logMessages[0], "Oops! Can't find log message ('" + testString + "')!..")
        else:
            self.fail("Oops! Log entry is not captured at all!..")
    else:
        self.fail("Oops! Neccessary log entry is not captured!.."){/syntaxhighlighter}</p><p><br>2. Далее есть набор классов, в которых переопределяются некоторые методы класса <strong>LogViewerTestBase</strong>, который в свою очередь создаёт:</p><ul><li>файлы логов, которые будут использоваться во время тестирования</li><li>класс LogViewManager cо специфическими параметрами</li></ul><p style="text-align: left;">Вот эти классы:</p><ul><li>LogViewerTestFileDelay</li><li>LogViewerTestIgnore</li><li>LogViewerTestWithOutFile</li><li>LogViewerTestWithTwoFiles</li></ul><p style="text-align: left;">Например, <strong>logViewerTestWithTwoFiles.py</strong>:<br><br>Этот класс организует проверку того, как два лога обрабатываются одновременно:</p><p>{syntaxhighlighter brush: python;light: true; fontsize: 100; first-line: 1; }class LogViewerTestWithTwoFiles(LogViewerTestBase):
""" Check log viewer processing situation when log file is absent... """

def __init__(self, methodName='runTest'):
    """ """
    LogViewerTestBase.__init__(self, methodName)
    self._logFile4Test2 = "./data/test2.log"

def setUp(self):
    """ Create second file and, then, default setup """
    self._createTestLogFile(self._logFile4Test2)
    LogViewerTestBase.setUp(self)

def tearDown(self):
    """ Clean default test environment and second file """
    LogViewerTestBase.tearDown(self)
    self._removeTestLogFile(self._logFile4Test2)

def _startLogViewManager(self):
    """ Start LogViewerManager with test parameters - with special log file and tag for watching """
    self._logViewerManager = LogViewerManager([self._logFile4Test, self._logFile4Test2], [self._tagNames])
    self._logViewerManager.testBegin(self._testName4LogViewer){/syntaxhighlighter}</p><p><br>3. Есть отдельный файл с параметрами, которые используют тесты - <strong>logViewerTestProperties.py</strong><br>Сейчас там такие пераметры:</p><ul><li>время, которое мы даём фреймворку на обнаружение новой записи в логе</li><li>настройка лога (да, да! лога тестов, которые тестируют то, как анализируются логи :-))</li></ul><p style="text-align: left;"><br>Вот диаграмма классов:<br><img src="http://2.bp.blogspot.com/_XFzJwPAOQgU/TDOuA5O1JTI/AAAAAAAAFwc/Nn_0FgF8t3g/s1600/logViewerTest+class+diagram.png" alt="logViewerTest class diagram" title="logViewerTest class diagram" width="704" height="395" class="mceItem"></p><p style="text-align: left;">P.S. Мне кажется, что тесты получились ни чуть не проще, чем тестируемая система... Ну, что ж вот <a href="http://www.sovmusic.ru/text.php?fname=ourduty" target="_blank">такая у нас работа!</a></p>