пятница, 21 января 2011 г.

О тестировании тестов

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

Итак, на что же можно обратить внимание при тестировании автотестов:

1. Тест должен делать то, что от него ожидается.

Такая проверка, пожалуй, самая простая и более всего похожая на обычное тестирование. В простейшем случае запускаем тест и удостоверяемся, что он выполняет предписанные действия (кстати, если автотест разрабатывается по написанному сценарию, сценарий тоже полезно тестировать - до ухода в разработку). Специфика, с которой мне пришлось столкнуться, заключалась в том, что при реализации автотестов разработчики могут больше обращать внимание на то, ЧТО должен сделать тест, и меньше - на то, КАК тест должен это делать. Разница может быть в нюансах, но ведь это всё-таки тест, для которого "КАК" может быть наиболее важно - иначе либо что-то не проверится, либо проверится не то, что предполагалось.

Пример 1. При нажатии на кнопку "Закрыть" на какой-то странице автоматически выполняется переход на заглавную страницу приложения. При реализации автотеста, вместо нажатия на кнопку и ожидания автоматического перехода, был реализован прямой переход на заглавную страницу приложения.

2. Если что-то идёт не так, тест должен адекватно реагировать.

В этом суть теста - если возникает проблема, тест должен её выявлять. Поэтому при тестировании автотестов такие проверки особенно важны. И они же сложнее - нужно ещё суметь создать ошибочную ситуацию, чтобы скормить её автотесту, чтобы проверить, как он на неё отреагирует. Что-то, конечно, проверяется и на реальных проблемах.

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

3. Тест должен корректно отрабатывать как сам по себе, так и будучи запущенным в пачке с другими тестами.

В наибольшей степени это вопрос корректной проверки и создания предварительных условий до выполнения теста и выполнения "зачистки" после теста. Когда запущено несколько тестов подряд, недочёты в проектировании тестов по данным вопросам очень хорошо проявляются.

Пример 3 (примитивный). Автотест-1 проверяет корректность создания какого-то объекта. Следующий за ним Автотест-2, проверяющий другой способ создания объекта, завершается ошибкой, поскольку объект уже существует, т.к. был создан и не удалён в рамках предыдущего Автотеста-1.

4. (Развитие п.3) Тест должен корректно отрабатывать как в случае успешного выполнения, так и в случае обнаружения ошибки.

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

Пример 4. Автотест-1 отключает некий сервис и проверяет при этом корректность обработки ошибок. После завершения проверок сервис снова включается. Однако когда Автотест-1 обнаруживал ошибку и аварийно завершался, при этом аварийном завершении включение сервиса не было предусмотрено. Следующие за Автотестом-1 тесты дружно завершались ошибками.

5. Тест должен корректно отрабатывать при различных условиях, в которых может работать тестируемое приложение.

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

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

6. Если тест обнаруживает ошибку, он должен правильно о ней сообщать.

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

Пример 6. При выполнении автотеста переходим со страницы-1 на страницу-2, оттуда - на страницу-3, где в конце концов жмём на кнопку. По результатам выполнения теста мы получили информацию, что тест завершился с ошибкой, потому что кнопка недоступна. А на самом деле - мы так и остались на странице-1 и даже на страницу-2 по каким-то причинам перебраться не смогли.

Пожалуй, список получился простым. И при грамотном проектировании автотестов все эти моменты должны быть учтены. Однако если команда только начинает работать над автоматизацией и не имеет в этом особого опыта - этот список может быть весьма актуальным. Лично у меня по нему при текущем состоянии автотестов ещё масса работы, и это не считая специфических для проекта вещей, которые я не смогла или не посчитала целесообразным обобщить и описать в этой заметке. Успехов всем идущим по пути автоматизации ;)

16 комментариев:

  1. О, моя любимая тема!
    Ссылка на презентаху, с SQA Days 5. К сожалению без звука:
    http://www.slideshare.net/VLDCORP/ss-1367042

    Надеюсь у меня как-нибудь появится время вернуться к работе над этим инструментом.

    ОтветитьУдалить
  2. В целом все по делу. Есть коментарий по пункту №5 "Тест должен корректно отрабатывать при различных условиях, в которых может работать тестируемое приложение".
    Все зависит от того, что считать корректной работой. Да, в зависимости от внешних условий тест не должен вести себя неправильно (сообщать об ошибке, когда ее нет или не сообщать, когда есть) или вообще вываливаться по какому-нибудь нежданному исключению.
    Но вполне возможно, что тест в данных условиях становится неприменим (например: тест для винды, запущеный на солярке или тест попавший в ограниченные условия по безопасности) - в данном случае тест должен или упасть с адекватным сообщением или наоборот пройти ничего не делая, но с адекватным сообщением. У нас, например, тесты которые не могут быть выполнены по соображениям установленной политики по безопастности проходят с сообщением типа "Required permission '...' is not granted. Passed."

    ОтветитьУдалить
  3. Хм, спасибо за линк. Помнится, я как-то невнимательно просмотрела презентацию, когда впервые её увидела, отпугнувшись тем, что речь вроде как шла о unit-тестировании, к которому я отношения не имею.

    Но вот сейчас просмотрев внимательно, вижу, что тема мне действительно близка, несмотря на то, что речь всё-таки идёт о других тестах, нежели у меня.

    Интересная вообще мысль автоматизировать тестирование автоматических тестов %)Вот только не уверена, что для наших автоматических _функциональных_ тестов это может быть применимо.

    Хотя вот мысль о том, чтобы специально вносить ошибки в приложением, чтобы проверить автотесты, - приходила мне в голову. Но быстро оттуда ушла, потому что я представила, как меня будут убивать разработчики, если я им о подобном заикнусь %)

    А вообще надо обо всём этом хорошенько подумать :)

    ОтветитьУдалить
  4. Спасибо, Алексей, честно говоря, с пунктом 5 действительно есть вопросы.

    Мы вот столкнулись с ситуацией очень высокой нагрузки на сервер и, вероятно, очень плохой связи. Вручную работать с приложением в принципе возможно, хотя оно будет периодически ругаться, что связь потеряна, будет её снова восстанавливать и как-то дальше работать.

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

    С нашими автотестами нам ещё надо по этим вопросам думать и разбираться.

    ОтветитьУдалить
  5. >Вот и на моём текущем проекте стали активно
    >разрабатываться автоматические тесты для
    >функционального и системного тестирования

    а продукт упомяните, please

    ОтветитьУдалить
  6. Если я правильно поняла вопрос, то у нас используется Selenium.
    Или вы про название моего проекта?? %)

    ОтветитьУдалить
  7. Кстати, необязательно делать "бажной" именно тестируемую имплементацию. Можно поиграть с сервисами и, если есть, с тестовым фреймворком. Например:
    1) Тесты должны тестировать сайт с урлом http://mysite.com Как поведут себя тесты если там нет никакого сайта? Как поведут себя тесты, если сайт медленно отвечает (ваш вариант) - это ведь можно искусственно смоделировать.
    2) Если есть единый тестовый фреймворк, который используют тесты, то можно - например сломать метод login - и посмотреть какие тесты без этого пройдут. Тут варианты такие - либо тесту не нужен логин, либо тест не использует фреймворк, а логинится напрямую (что не очень хорошо), ну и либо тест плохой и требуется переделка.

    ОтветитьУдалить
  8. У меня такое впечатление, что я как-то неправильно понимаю понятие "фреймворк". Потому как фразу "либо тест не использует фреймворк" я вообще понять не могу :( Что такое "тестовый фреймворк"?

    ОтветитьУдалить
  9. В моем понимании (ну и внаших продуктах тоже) - тестовый фреймворк - это набор библиотечных классов, предоставляющих сервисы и функции для всех тестов. Например, чтобы в каждом тесте не писать, что надо заологиниться туда-то, с такими-то параметрами и делать это надо так-то --- есть какой-нибудь класс с методом который выглядит как-то так: login(username, password), и который все тесты вызывают, когда им нужно залогиниться в систему перед непосредственно тестированием. Если процедура логина в программе меняется - надо поменять только один метод во фреймворке, а все тесты остаются как были.
    Например, для ajax делают специальные фреймворочные функции, которые дожидаются загрузки элементов на страницу.Ну и так далее.

    ОтветитьУдалить
  10. А, ну тогда я всё-таки, видимо, правильно понимаю. Например, для того же логина функция у нас одна и есть, и дёргается во всех тестах.

    Я просто представить себе не могла, как можно _не_ использовать фреймворк - потому, что у нас это само собой (опять же, если я всё правильно понимаю): у нас разрабатывается единый набор методов, а тесты уже составляются как из кирпичиков из этих методов.

    ОтветитьУдалить
  11. >Если я правильно поняла вопрос, то у нас
    >используется Selenium.

    правильно. спасибо.

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

    ОтветитьУдалить
  13. ...учитывая, что у нас фреймворк используется по умолчанию...
    Как я понял, задача - проверить тесты. Соотвественно такое заявление тоже нужно/можно проверить, тем более, что особых усилий не требуется.

    ОтветитьУдалить
  14. Наверное, мне лучше уточнить, как у нас всё устроено, чтоб не оказалось, что я несу чушь или типа того :)

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

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

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

    Может я неправильно понимаю ваш последний комментарий - поясните плз...

    ОтветитьУдалить
  15. Понятно, я как-то не подумал о такой организации тестов. Тогда да, сам тестовый фреймворк курочить смысла особого нет.

    ОтветитьУдалить
  16. Ясно, спасибо, теперь хоть буду более ли менее уверена, что я всё более ли менее правильно понимаю :)

    ОтветитьУдалить