Здравствуйте!
В прошлом выпуске мы остановились на том, что
- автоматические проверки ПО лучше ручного тестирования и
- дешевле делать эти проверки с самого начала разработки проверяемого ПО.
В этом выпуске мы начнём разговор о том, как реализовать проверку ПО, если делать это с самого начала разработки.
Проектирование для проверяемости
Первое, если не главное, что Вы можете сделать для простой проверяемости Вашего ПО (на начальном этапе разработки) – это спроектировать Вашу программу так, чтобы её можно было легко протестировать.
Во-первых, весь функционал стоит распределить по модулям.
Во-вторых, у каждого модуля надо выделить 2 части:
а) Описательную и
б) Реализующую.
Описательная часть – это интерфейс модуля во внешний мир, то, что о нём знают другие модули. Описательная часть содержит информацию о том, какие полезные для других модулей функции он поддерживает. Описательная часть не содержит в себе тонкости реализации этих функций, которые неинтересны другим модулям.
Микроволновая аналогия
Аналогия. Предположим, у Вас есть микроволновая печь. На ней есть красивая панелька, с помощью которой Вы можете ввести мощность и длительность облучения, а также кнопка для запуска работы печи. Эта панелька – описательная часть микроволновой печи.
Кроме описательной части есть ещё реализация – это все агрегаты, которые скрываются за этой панелькой. Там есть
- клистроновая лампа для облучения,
- есть мотор для вращения тарелки,
- есть трансформатор для преобразования переменного тока в постоянный,
- есть экран, благодаря которому можно стоять рядом с печью во время её работы и не беспокоиться, что после этого не будет детей и т. д.
Однако все эти тонкости пользователю печи (другим модулям) неинтересны и даже опасны. Поэтому пользователь может делать только то, что позволяет делать ему панелька (описательная часть).
Золотое правило
Возвращаемся к нашим модулям. Если всё сделать так, как я здесь описал, то приложение будет состоять из набора модулей. Каждый знает друг о друге только то, что прописано в описательной части.
Информация, которой они обмениваются, тоже находится в том или ином описательном модуле.
Как правило, в приложении есть только один модуль (одно место), в котором используются реализующие части модулей.
Чтобы такое приложение можно было дёшево протестировать, нужно соблюдать некоторые правила. Одно из основных гласит: В описательной части модуля должны находиться только
- соглашения (interfaces) и
- абстрактные классы.
Из этого правила следует, что модули обмениваются между собой информацией, которая передаётся через соглашения (interfaces), а не через конкретные классы. Это имеет ключевое значение для проверяемости приложений.
Заглушки
Допустим, у Вас есть некий модуль Калькулятор, который берёт данные из модуля БазаДанных, выполняет над ними какие-то операции и записывает результаты обратно в базу данных.
Предположим далее, что Вы спроектировали Ваше ПО согласно описанным здесь правилам.
Если Вы хотите проверить работу модуля Калькулятор (т. е. выявить дефекты этого модуля), Вы можете поступить следующим образом:
- Модуль Калькулятор знает только о том, какие функции поддерживает модуль БазаДанных, но ничего не знает о реализации этого модуля.
- Другими словами – модуль Калькулятор не знает, что скрывается за «панелькой» модуля БазаДанных – SQL Server, MySQL или просто текстовый файл.
- Вместо настоящей базы данных, мы можем передать модулю Калькулятор объект-заглушку (mock object), который реализует соглашение модуля БазаДанных, но базой данных не является.
- Таким образом мы можем снизить сложность (значит и стоимость) этой проверочной программы, т. к. нам не надо заботиться о соединении с базой данных, наличием в ней нужных записей и т. д. Мы можем без особого труда протестировать модуль Калькулятор в изоляции от других модулей.
Ради этого и делается разделение приложения на модули, а каждого модуля на описательную и реализующую часть.
В следующей записи мы поговорим о том, какие бывают модули и как их следует тестировать.
Успехов
Дмитрий Писаренко