61
50 оттенков красного Или тестирование без боли Сергей Александрович, @darth_sim

2015-03-07 03 Сергей Александрович. 50 оттенков красного

  • Upload
    -

  • View
    38

  • Download
    1

Embed Size (px)

Citation preview

Page 1: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

50 оттенков красногоИли тестирование без боли

Сергей Александрович, @darth_sim

Page 2: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Немного о себеМеня зовут СергейЯ разрабатываю backend у Злых МарсианЯ люблю писать тесты

Page 3: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Сегодня мы:Поговорим о том, зачем мы пишем тесты;Уменьшим объем тестов без потери качества;Уменьшим время написания и цену тестов;Упростим поддержку.

Page 4: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

DisclaimerСпорить о тестах можно много и долго. Все сказанное

здесь - мое мнение, основанное на личном опыте

Page 5: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Спонсор многих слайдов

Page 6: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему нужно писатьтесты?

Page 7: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему нужно писать тесты?Чтобы беречь свое время при разработке;

Факт от Капитана: автоматические тесты выполняются напорядок быстрее ручных.

Page 8: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему нужно писать тесты?Чтобы беречь свое время при разработке;Чтобы не бояться что-то сломать;

Факт от Капитана: Все делают ошибки. Кто не делаетошибок, тот нагло врет.

Page 9: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему нужно писать тесты?Чтобы беречь свое время при разработке;Чтобы не бояться что-то сломать;Чтобы держать архитектуру приложения в форме.(касается в основном unit-тестов)

Page 10: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему нужно писать тесты?Тесты - это взгляд на код со стороны.

Код сложно тестировать? ⬇

Код сложен, запутан ⬇

Код нуждается в рефакторинге

Page 11: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему иногда мы не пишемтесты?

Потому что часто тесты выглядят вот так:

Page 12: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Пора навести порядок!

Page 13: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test coverage

Page 14: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test coverageОднажды программист спроcил Великого

Мастера: «Какого покрытия тестами я должендостичь?»

goo.gl/NH84c6

Page 15: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test coverageНе дает никакого представления о том, насколькохорошо протестирован код;Показывает, какие места точно не протестированы, ноне наоборот;Не дает никакого представления о качестве кода;Не та метрика, за которой стоит гнаться.

Page 16: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test coverage100% не стоит вашего времени;90% — это очень хорошее покрытие;70% вполне достаточно.

Page 17: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test coverage“Мне платят за код, который работает, а не затесты, поэтому моя философия заключается в

том, чтобы тестировать настолько мало,насколько это возможно для достижения

нужного уровня уверенности„(Кент Бек)

Page 18: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнее

Page 19: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнееТесты некритичного кода

Если ошибка в коде не повлечет за собой серьезныхпоследствий, то тестирование этого участка кода совсем

не обязательно.

Page 20: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнееТесты поведения сторонних библиотек

Большинство библиотек уже протестированыразработчиком;Если вас не устраивает, как они протестированы, лучшесделать контрибьют, чем держать тесты у себя.

Page 21: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнееКосвенно выполненные проверки

Проверка на наличие классов и методов;Проверка количества аргументов функций;Проверка на отсутствие исключений.Иногда такие проверки необходимы, но такие случаиредки.

Page 22: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнееТесты приватных методов

Приватные методы проверяются тестами открытыхметодов, в которых они вызываются

Page 23: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Выбрасываем лишнееТесты тривиального кода

“Если я не делаю ошибок какого-то рода, я нетестирую код на их наличие„

(Кент Бек)

Page 24: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Приводим оставшееся впорядок

Page 25: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Приводим оставшееся в порядок“Пишите код так, как будто сопровождатьего будет склонный к насилию психопат,

который знает, где вы живёте„(Мартин Голдинг)

Верно и для тестов.

Page 26: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте говорящие именатестов

Тест — это спецификация с функцией самопроверки. Поназванию теста должно быть понятно, что конкретно он

проверяет.

Page 27: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте говорящие именатестов

Bad:

it 'works' do # ... end

Good:

it 'sends email to the user' do # ... end

Page 28: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте говорящие именатестов

Если фреймворк не позволяет в полной мере описать тестс помощью имени, напишите комментарий

# Sends email to the user def test_send_message # ... end

Page 29: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Один тест - одна проверкаПо выводу тестового фреймворка должно быть понятно,

какие конкретно действия выполняются не так, какожидалось.

Page 30: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Один тест - одна проверкаBad:

it 'creates message and sends it to the user via email' do # ... end

Good:

it 'creates message' do # ... end

it 'sends message to the user via email' do # ... end

Page 31: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Один тест - одна проверкаАналогично для фреймворков без возможности подробно

описать тест

# Creates message def test_send_message__message_creation # ... end

# Sends message to user def test_send_message__message_sending # ... end

Page 32: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Один тест - одна проверкаНекоторые фреймворки позволяют писать комментарии к

проверкам. В таком случае разделение не так важно.Пример для testify (go):

// Creates message func Test_sendMessage(t *testing.T) { // ... assert.Equal(t, expected, actual, "Should create message") // ... assert.Equal(t, expected, actual, "Should send message to user via email") // ... }

Page 33: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте контекстыЕсли фреймворк позволяет задавать контекст

тестирования — пользуйтесь этой возможностью

Page 34: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте контекстыBad:

it 'creates message when user is signed in' do sign_in(user) # ... end

Good:

context 'when user is signed in' do before { sign_in(user) }

it 'creates message' do # ... end end

Page 35: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Используйте контекстыЕсли фреймворк не поддерживает контексты, можно опять

обратиться к комментариям

# = When user is signed in ============================== # Creates message def test_send_message__signed_in__message_creation # ... end # = end When user is signed in

Page 36: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Правильные ожиданияПравильно подобраное ожидание - половина написанного

теста.

Page 37: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Правильные ожиданияПримеры хороших ожиданий:

Возвращаемое значение;Изменения состояния класса, видимого извне;Внешнее воздействие a.k.a. side effect;Обращение к сторонним объектам.

Page 38: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Правильные ожиданияПримеры плохих ожиданий:

Изменения внутренних переменных класса;Изменение состояния хранилища, используемого дляхранения состояния тестируемого объекта;Вызовы приватных методов.

Page 39: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Правильные ожиданияBad:

it "puts provided value to redis" do subject.set("the value") expect(REDIS.get("the key")).to eq("the value") end

Good:

it "saves provided value" do subject.set("the value") expect(subject.get).to eq("the value") end

Page 40: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Правильные ожиданияСтарайтесь максимально абстрагироваться от реализации

метода и сосредототочиться на результате

Page 41: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Mocks & stubsПалка о двух концах:

Помогают достичь нужного уровня изоляции;При злоупотреблении могут сделать тест бесполезным.

Page 42: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Mocks & stubsХорошие кандидаты:

Передаваемые на вход объекты;Сетевые службы;Функции с трудно прогнозируемым или трудновыводимым результатом, используемые в тестируемомметоде.

Page 43: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Mocks & stubsНужно очень осторожно подходить к стабу БД.

Если не уверены на 100%, не делайте этого

Page 44: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиСитуация №1:

Функция foo объекта A (A.foo) проводит вычисления сосложной логикой, основываясь на результатах функцииbar объекта B (B.bar);B.bar в свою очередь тоже проводит вычисления сосложной логикой.

Необходимо протестировать метод A.foo

Page 45: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №1:

Написать тест, учитывающий логику функции B.bar.

Нарушение DRY, повторное тестирование B.bar,тестирование логики, не относящейся к тестируемому

методу

Page 46: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №2:

Создать условия для получения заранее известногорезультата B.bar, использовать этот результат для

тестирования A.foo.

Тест становится зависимым от логики B.bar.Изменение логики стороннего метода сломает тест.

Page 47: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №3:

Сделать stub B.bar с известным результатом,использовать этот результат для тестирования A.foo.

Тест не зависит от логики B.bar

Page 48: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиПроблема варианта №3: Изменение интерфейсафункции B.bar сломает код, но оставит тест ложно

положительным.

Решение: Это тот самый случай, когда чистый прогонфункции с проверкой на отсутствие исключений имеет

место быть.

Page 49: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиСитуация №2:

Метод foo объекта A (A.foo) проводит вычисления сосложной логикой и затем вызывает метод bar объекта B(B.bar);B.bar в свою очередь тоже реализует сложную логику.

Необходимо протестировать метод A.foo

Page 50: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №1:

Проверить side effect метода B.bar, учитывая его логику.

Нарушение DRY, повторное тестирование B.bar,тестирование логики, не относящейся к тестируемому

методу

Page 51: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №2:

Проверить некоторую неизменную часть side effect'аметода B.bar, не зависящую от его логики. Пример: mailer

отправляет письмо с неизменным заголовком.

Тест не зависит от логики B.bar. Изменениеинтерфейса B.bar будет обнаружено сразу.

Page 52: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Работа с внешними связямиВариант решения №3:

Сделать stub B.bar, проверить факт его вызова послевыполнения A.foo.

Тест не зависит от логики B.bar

Имеет ту же проблему и аналогичное решение, что ивариант решения №3 предыдущей ситуации.

Page 53: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Гораздо лучше!

Page 54: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Поддерживаем порядок

Page 55: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Составьте договоренностиЕсли работаете в команде, составьте styleguide для тестов,

хотя бы на словах. Это существенно снизит порогвхождения в чужие тесты.

Page 56: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test first!“Не доверяй тесту, который ты не видел

упавшим„(народная мудрость)

Page 57: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему test first?Если строить код на основе тестов, то у вас практическине возникнет проблем с тестируемостью;Хорошо организованные тесты позволяют продумать иописать структуру кода до реализации.

Page 58: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Почему test first?Главный аргумент

Не зная точной реализации, вы будете вынужденытестировать только интерфейс, что и требуется

Page 59: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

Test firstПеред написанием тестов, постройте дерево с помощью

контекстов. Постарайтесь отобразить все возможныеварианты развития событий.

Page 60: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

ИтогиНе гонитесь за test coverage;Не будьте параноиком, определите для себя, что нужнотестировать;Описывайте тесты так, чтобы другой человек мог понятьтестируемый функционал;Тестируйте интерфейс, а не реализацию;Делайте unit-тесты независимыми от функционаладругих классов/методов;Используйте тесты как спецификацию для вашего кода;

Page 61: 2015-03-07 03 Сергей Александрович. 50 оттенков красного

СпасибоВопросы?