Comments 19
Спасибо за шикарный материал.
def test_random_real(): assert 0 <= get_thing() < 10
Я думаю это плохой тест. Предположим произошла ошибка и рандом стал возвращать числа до 10 включительно. О такой ошибке тест может сообщить очень не скоро.
Плохой, да.
Например, вы ещё и закладку не найдёте, если на каждой итерации №№317-350 будут выдаваться нули.
Но тут важно ведь не слепое следование примеру...
А этот метод я бы вообще тестами не покрывал, ибо он не содержит логики. А если бы он содержал логику, завязанную на рандомные числа, то я бы предпочел замокать рандом, тем самым упростив тест и сделав его стабильным. Здесь, очевидно, нужен компромис.
Что я хотел сказать: данный пример, на мой взгляд, не защищает точку зрения, изложенную в статье :)
Если что, это не «спервадобейся», а вполне серьёзный вопрос — мне интересно узнать.
У нас в приложении есть плеер, который имеет режим смешивания. Необходимо убедиться что функция смешивания работает. Сначала нужно определить, что для меня будет достаточным доказательством. Как бы я тестировал руками? Выбрал бы трек из середины списка, включил режим смешивания, нажал на кнопку «следующий трек» и проверил что новый трек не является следующим по списку, и не является треком который мы изначально выбрали. Т.е. он «любой другой, кроме». Мы не проверяем работу рандомизатора, мы проверяем функцию приложения, на соответствие заявленному поведению. Этот тест не дает нам абсолютной гарантии верного поведения, потому что рандомизация может перестать работать после второго нажатия по кнопке «след. трек». Но оно достаточное, чтобы двигаться дальше по покрытию. Усилить тест можно потом, в случае необходимости, если будут прецеденты.
Чтобы не залезть в дебри и не начать тестировать совсем не то что нужно, в совершенно неоправданных объемах, а быстро двигаться вперед, порой помогает вслух спросить себя «что является предметом теста?».
Забавно, но в соседней статье на хабре обсуждают очень близкую тему: https://habrahabr.ru/company/infopulse/blog/336110/#comment_10377980
Ответ будет длинным.
Совсем избавить UI-тесты от тавтологий, наверное, не получится. Причина как в раз в том, что же мы хотим проверить — мы хотим убедиться что поведения правильное или что поведение соответствует ожидаемому? Правильное поведение должно быть протестировано вручную или с помощью TDD, с привлечением документации или хотя бы с помощью здравого смысла и постановщика задачи. Протестировать то, что ожидаемое поведение не нарушено — это, по сути, регрессионное тестирование. В части задач (например, ежедневные выкладки) целенаправленно тесты пишутся именно таким образом.
Но можно убрать тавтологию в компонентах, на которые мы делим тест или проверяем. Например, мы знаем, что определённая компонента подвергается постоянным изменениям. Так ли нам важно проверять, что элемент <div id="test">new text</div>
является div-ом, не достаточно ли проверять элемент #test
? Кажется очевидным, но это пример простой. В реальных тестах всё довольно сложнее.
Ну, например, выпилил проверку того, всплывающее сообщение с каким текстом показывается после той или иной операции. Там нет текста, соответствующего ошибке? Значит, тест будет считать, что операция завершилась успешно и продолжать своё выполнение: ему нужно убедиться, что, например, покупка прошла и поменялись балансы. Поменялись? Отлично.
А проверку того, какое облачко будет показываться после покупки (например) — мы будем делать в тепличных условиях и проверять будем только это.
Короче. Порой надо проверять компоненты, а порой — сценарии. Если нужен сценарий, то выпиливайте подробную проверку компонент.
По-моему, так.
Меня и по сей день регулярно посещает мысль, что компоненты должны быть тоже протестированы перед тем как гонять сценарии. Но наша задача проверить работу нашей части приложения, а не проверять фреймворк и пр. Поэтому так и живем.
исходник на гитхаб
public void testCreateWithNoInitialText() throws Throwable {
View createMenu = view(id.m_apply);
assertFalse(createMenu.isEnabled());
EditText content = editText(id.et_gist_content);
focus(content);
send("gist content");
assertTrue(createMenu.isEnabled());
}
Закроем на минуту один из наших внимательных глаз на то, что впринципе несколько утверждений в одном тесте вобщем спорная, а в большинстве случаев довольно «прохладная тема».
Какая польза от первого утверждения? Он оберегает тест от ситуациии когда тест пройдет несмотря на то что страница была изначально активна. Значит посылание текста в активную страницу тестом не распознается. Вопрос: а является ли это ошибкой? Если да, то это должно быть протестированно отдельно. Если нет, то это входное условие лишнее.
Тавтологические тесты