Вход:  Пароль:  
FreeSource: WINE/WritingTests ...
Free Source | Каталог | Изменения | НовыеКомментарии | Пользователи | Регистрация |

Написание тестов в системе Wine

Вступление


Для чего нужны тесты и зачем разработка под Wine требует их написания?


Сперва стоит уточнить, что мы занимаемся разработкой, доработкой и поддержкой нашего продукта WINE@Etersoft, который базируется на свободном проекте Wine.


Но 80% работы – это системная отладка: поиск и безжалостное уничтожение ошибок, бесконечная шлифовка кода Wine, высшая форма которой является признание получившегося патча сообществом Wine и включение его в cvs. Поэтому тесты необходимы. На нынешнем этапе развития Wine уже реализовано порядка 20 000 функций WinAPI и невозможно прикладывать отдельно каждый патч и проверять – вносит ли он полезные изменения и что более важно – не ломает ли он уже работающее? Сегодня практически стало стандартом, когда вместе с отправкой патча высылается тест, наглядно демонстрирующий изменения, вносимые исправлением. Но в ряде случаев очень приветствуется и простое написание тестов, демонстрирующие ошибки или различия реализации Win API? в ОС разных версий, так как это позволяет «задокументировать» проблему и иметь надёжный способ её повторить ( ведь не всем же нравится читать описание на пол экрана как проявляется бага, а затем ещё пол часа тыкать мышкой :) ).


Хорошо написанный тест чётко показывает различие в реализации API в Wine и Windows, он может прогоняться автоматически, т.к. должен быть интегрирован в систему тестирования Wine. «Наша» ситуация – это тест ИДЕАЛЬНО проходит в Windows, но однозначно и постоянно падает в одном и том же месте, будучи запущенным в Wine, только после этого можно приступать к исправлению ошибки. Кстати, грамотно написанный тест автоматически убавляет 50% работы, потому что часто не сложно исправить ошибку, но очень трудно локализовать её.


И ещё одно: существующий тест – это весьма весомый аргумент при принятии исправлений, который позволяет на тратить много слов на объяснения вида «Но как это работает, и почему в Windows это устроено так неординарно (глупо)?!". Плюс, если кто-то поломает что-то в том же модуле, в котором Вы вносили исправления, то тест лишает Вас головной боли вида: «От чего отлаженный механизм перестал работать?», – и позволяет быстро найти вредителя, откладывая патчи и прогоняя тест. Поверьте – хороший тест сэкономит Вам кучу времени и нервов, а это очень дорогие вещи сейчас.

Main part


TOOLS
Прежде чем рассказывать про написание тестов, было бы неплохо поговорить о функциях, которыми мы будем пользоваться повсеместно, их немного, но они незаменимы.


void traсe( const char *msg, ... )
– аналог вездесущего printf(), с той лишь разницей, что printf() в тестах использовать строго НЕ РЕКОМЕНДУЕТСЯ, т.к. printf() просто выводит текст, а trace() так же просто его выводит, но при выводе указывает модуль и имя функции откуда вызван, поэтому printf() просто неинформативен. Во время написания тестов забудь про него.


int ok( int condition, const char *msg, ... )
– модификация trace(). Самая главная функция, без неё тест – не тест, а вся соль в первом параметре. Туда передаётся логическое условие, если это условие TRUE, то функция ничего не выводит и счётчик УСПЕШНО пройденных тестов инкрементируется. Если FALSE, то функция дальше работает как trace(), просто выводит всё что ей запихнули, но самое главное – предваряет вывод строчки отображением ругательства «test failed: ваша строка» – данная строчка – это заклинание, которое позволяет находить среди горы информации, переданной в поток вывода, тесты, которые упали. Счётчик ПРОВАЛЕННЫХ тестов также плюсуется.


Пример:
ok(!result && Get Last Error?()==ERROR_MORE_DATA, «expected %i, got %d\n», ERROR_MORE_DATA, Get Last Error?());
В случае провала функция выведет : expected ERROR_MORE_DATA ( в виде константы), got Get Last Error?() (выведет номер ошибки).


MAKE CROSSTEST


Первая часть повествования будет рассказывать о том как внедриться в уже готовые тесты и вероломно затестировать то что надо. Для начала было бы неплохо найти куда пихать свой тест. Обычно это дело тривиальное, но иногда случаются проблемы. Рассмотрим три случая.


Случай первый:


Допустим мы хотим написать тест для виджета(контроля) Listbox, Вы обнаружили ошибку, что ListBox неверно реагирует на сообщение LB_ADDSTRING. Наши действия:

  1. Разведать где находится test case для listbox. Агентура сообщает, что это находится в том же модуле где и сам listbox, только в каталоге tests. Итоговый путь: dlls/user32/tests/listbox.c.
  2. Найти функцию, куда следует добавить наши 2 – 3 строчки, если же такой функции нет, то дополнительное задание – придумать ей имя и её создать. В нашем случае это будет функция static void test_listbox_height(void).
  3. Собственно тестируем :
id = Send Message?( hList, LB_ADDSTRING, 0, (LPARAM) “hi”);
ok( id == 0, «item id wrong\n»);

Правда всё просто?


Ремарка: Если же пришлось создавать свою функцию, то чтобы она запустилась при прогоне теста, следует в самом конце модуля внутри функции START_TEST(имя тестового модуля) добавить вызов своей функции:
START_TEST(listbox)
{

test_listbox_height();

}


Компилируем командой make crosstest. Исправляем ошибки. Компилируем ещё раз. Запускаем, говоря ww user32_test.exe.so listbox, и радуемся результату:
listbox: 345 tests executed (0 marked as todo, 0 failures), 0 skipped.


Случай второй:


Допустим мы хотим написать тест для модуля, а каталоге ../tests/такого_модуля_нет.c. Что же тогда делать? А искать по тем модулям которые есть. Делается это несложно – ищутся вызовы функций, которые требуется протестировать, в тестовых модулях. Просматриваются объёмные тестовые модули, аналогов которых нет в исходной библиотеке.
Пример:
Мы хотим протестировать сообщения, которые семантически относятся к модулю mdi.c в user32.dll. В каталоге tests такого модуля нет, но есть весьма объёмный модуль msg.c, и там как раз есть функция static void test_mdi_messages(void), в которой тестируется функциональность mdi.c. Туда и пишем наш тест.


Ремарка: Если вообще никак не найти модуль, куда можно внедрить свой тест, и поиски ни к чему не приводят, то это случай третий.


Случай третий:
(Это когда вообще всё плохо).
Если Вы читаете этот случай, то это говорит о том, что для модуля, который Вы хотите протестировать, нет test case.
Что ж – мы программисты, поэтому будем делать это ручками. А как – мы это рассмотрим во второй части данной главы, которая будет полностью посвящена созданию своих тестов. Если Вы только начинаете писать тесты, то я крайне советую в целях обучения написать пару-тройку тестов для тех модулей, которые уже есть, благодаря этому Вы приобретёте достаточно навыков для написания собственных тестов.

Share your ideas


Часто, после написания теста, есть смысл поделиться им с сообществом разработчиков wine. Несколько слов об оформлении тестов для отправки их в рассылку.


Глобально в Wine тесты делятся на два вила:
1. Тест успешно проходит в Windows и в Wine.
2. Тест успешно проходит в Windows, но проваливается в Wine.


Все остальные тесты считаются по-умолчанию неверными.


Тесты из первой группы являются регресс-тестами, либо тестами-пояснениями. Никакого особого оформления к ним не требуется.
Исключение правда составляют тесты на последовательность (функция ok_sequence(...)), где последний параметр-флаг должен быть выставлен как FALSE, что говорит о том, что тестируемое поведение не требует доработки и соответствует поведению эталона


Для оформления тестов второй группы существует несколько несложных правил:
1. Если для тестирования используется функция ok(...), то перед её вызовом необходимо поставить оператор todo_wine{ }, это будет символизировать то, что функционирование Wine, при данных условиях, отличается от работы Windows и Wine следует доработать.
2. Если для тестирования используется функция ok_sequence(...), то последний параметр-флаг должен быть выставлен как TRUE, по тем же причинам, что и в пункте 1.


Несколько правил об отправке тестов в рассылку:
1. Если отправляется тест из второй группы вместе с исправлением неправильной работы Wine одним патчем, то todo_wine или TRUE в ok_sequence(...) выставлять не следует, но стоит описать в теле письма, то что добавляется тест и сразу исправление кода.
2. Если отправляется только тест из второй группы отдельным письмом, то он оформляется в соответствии с правилами.
3. Если отправляется только тест из второй группы отдельным письмом, а затем следующим письмом исправление, основанное на этом тесте, то в исправлении должны быть строчки, убирающие todo_wine из теста, либо выставляющие FALSE флагу функции ok_sequence(...).


Описание создания тестов из оригинальной документации:
http://www.winehq.org/site/docs/winedev-guide/testing


Страницы, ссылающиеся на данную: WINE
WINE/Разработчику


 
Файлов нет. [Показать файлы/форму]
Комментариев нет. [Показать комментарии/форму]