Тестирование и логирование — азы программирования

Тесты и нормально организованная трассировка — основные принципы создания больших программных систем. Но чаще всего в них не верят: тратят кучу времени на поиск незначительных ошибок и читают километровые тексты из консолей. Такое встречается даже у программистов с опытом работы несколько лет.

Итак, как мы реализовали эти принципы при создании сервера:

Тесты

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

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

Очень часто я слышу от программистов, что некогда писать тесты, что надо писать код, или нашу программу невозможно протестировать, она супер уникальная и тесты для неё придумать нельзя. По-моему мнению, есть конечно программы, которые сложно тестировать, например GUI (хотя и для них есть системы тестирования). Но в большинстве случае все тестируется. А что касается затрат времени на тесты, они окупаются сокращением времени при отладке. И код писать надо сразу же с учетом его тестирования, тогда и код получается красивым, и тест сам собой пишется.

Логирование

Чаще всего серверные программы — это некоторые черные ящики, без GUI интерфейса. А программисту важно знать, что же происходит внутри. И начинается. Сплошные trace и System.out. В консоле тонны мусора, если учесть, что на сервере уже более 1000 классов. И непонятно, где начинается один trace, а заканчивается другой. А если над сервером работает несколько человек и каждый решает свою задачу?… В таком случае trace одного человека будет мешать другому, и работа превратится в ад.

К счастью, все придумано за нас, есть проект log4j. Достаточно маленький проект, но решает большую задачу — ведет логи. Логи могут записываться куда угодно: текстовые файлы, механизмы логирования операционных систем, XML формат и самый используемый у нас метод — запись в сокет. Важно и то обстоятельство, что это стандарт. И скорее всего, сторонние библиотеки также будут использовать вашу систему логирования. Например, достаточно просто интегрируется JUNIT.

А далее все просто. Ставится программа для просмотра событий chainsaw. Она умеет получать логи с удаленных логеров. А самое главное, она умеет качественно их показывать. Фильтрация по типам, приоритетам, источникам.

Интеграция JUNIT и Log4j

 
/**
 * Реализация ResultPrinter для вывода сообщений JUnit в Log4J
 * 
 * @author Квиринг А.В (arts80)
 * 
 */
public class Log4jResultPrinter extends ResultPrinter {
 
    /**
     * @param writer
     */
    public Log4jResultPrinter() {
	super(null);
    }
 
    @Override
    public void addError(Test test, Throwable t) {
	Logger logger = Activator.instance.getLogger(test);
	logger.error(t.getMessage(), t);
    }
 
    @Override
    public void addFailure(Test test, AssertionFailedError t) {
	Logger logger = Activator.instance.getLogger(test);
	logger.error(t.getMessage() + "", t);
    }
 
    @Override
    public void endTest(Test test) {
	Logger logger = Activator.instance.getLogger(test);
	logger.info(test.toString());
    }
 
    @Override
    public void startTest(Test test) {
    }
 
}

Добавить комментарий