Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Тестируем тесты с PIT (мутационное тестирование)

307 views

Published on

Презентация подготовлена по материалам выступления Евгения Барановского на витебском Dev Day MiniQ (https://vk.com/devdayminiq), который был проведен 15 сентября 2016.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Тестируем тесты с PIT (мутационное тестирование)

  1. 1. ТЕСТИРУЕМ ТЕСТЫ С PIT 15 сентября 2016
  2. 2. Кто я? Евгений Барановский Я здесь, потому что люблю Java, качественный код и спокойствие. Связаться со мной меня можно через judzin.baranovsky@gmail.com.
  3. 3. План выступления ▷Текущие ограничения тестов ▷Мутационное тестирование ▷Мутационное тестирование с PIT ▷Проблемы мутационного тестирования ▷Будет много кода 
  4. 4. РАССМОТРИМ ПРИМЕР Нет ничего лучше примера
  5. 5. public class TimeLine { private int fetchCount; public TimeLine(int fetchCount) { setFetchCount(fetchCount); } public void setFetchCount(int fetchCount) { if (fetchCount <= 0) { throw new IllegalArgumentException("Count must be > 0"); } this.fetchCount = fetchCount; } public int getFetchCount() { return fetchCount; } // Some service logic, omitted for simplicity...... }
  6. 6. public class TimeLineTest { private TimeLine timeLine; @BeforeMethod protected void setUp() { timeLine = new TimeLine(10); } @Test public void shouldUpdateFetchCount() { int expected = 5; timeLine.setFetchCount(expected); assertEquals(timeLine.getFetchCount(), expected); } @Test(expectedExceptions = IllegalArgumentException.class) public void shouldNotAllowNegativeFetchCount() { timeLine.setFetchCount(-10); } }
  7. 7. Что же не так с традиционным тестированием?
  8. 8. Уберем вызов
  9. 9. ▷Успешно прошедшие тесты не всегда правы. ▷Существует много критериев покрытия кода. ▷И даже эти критерии могут быть неточными. Текущие ограничения
  10. 10. Это искусственный баг. Если набор тестов не в состоянии обнаружить мутацию, то он рассматривается как недостаточный. Мутация
  11. 11. Мутант – это система с мутациями. Мутант
  12. 12. в 1970х Причины низкой популярности: – недостаток технологий и – недостаток вычислительных мощностей. Мутационное тестирование было разработано еще
  13. 13. Итак, как работает мутационное тестирование? 1. Написать тест 2. Выбрать мутации 3. Получить мутантов 4. Прогнать тесты на мутантах 5. Пересмотреть тесты 6. Прогнать тесты снова
  14. 14. Итак, как работает мутационное тестирование? 2. Выбрать мутации 3. Получить мутантов 4. Прогнать тесты на мутантах 5. Пересмотреть тесты 6. Прогнать тесты снова 1. Написать тест
  15. 15. 1. Для знакомого класса ... public class TimeLine { private int fetchCount; public TimeLine(int fetchCount) { setFetchCount(fetchCount); } public void setFetchCount(int fetchCount) { if (fetchCount <= 0) { throw new IllegalArgumentException("Count must be > 0"); } this.fetchCount = fetchCount; } public int getFetchCount() { return fetchCount; } // Some service logic }
  16. 16. ... напишем такой тест @BeforeMethod protected void setUp() { timeLine = new TimeLine(10); } @Test public void shouldUpdateFetchCount() { int expected = 5; timeLine.setFetchCount(expected); assertEquals(timeLine.getFetchCount(), expected); } @Test(expectedExceptions = IllegalArgumentException.class) public void shouldNotAllowNegativeFetchCount() { timeLine.setFetchCount(-10); }
  17. 17. Итак, как работает мутационное тестирование? 1. Написать тест 3. Получить мутантов 4. Прогнать тесты на мутантах 5. Пересмотреть тесты 6. Прогнать тесты снова 2. Выбрать мутации
  18. 18. 2. Выбрать мутации для кода public class TimeLine { private int fetchCount; public TimeLine(int fetchCount) { setFetchCount(fetchCount); } public void setFetchCount(int fetchCount) { if (fetchCount <= 0) { throw new IllegalArgumentException("Count must be > 0"); } this.fetchCount = fetchCount; } public int getFetchCount() { return fetchCount; } // Some service logic } Можно удалить вызов Можно инвертировать условие Можно изменить границу условия
  19. 19. Итак, как работает мутационное тестирование? 1. Написать тест 2. Выбрать мутации 4. Прогнать тесты на мутантах 5. Пересмотреть тесты 6. Прогнать тесты снова 3. Получить мутантов
  20. 20. 3. Получить мутантов системы public class TimeLine { private int fetchCount; public TimeLine(int fetchCount) { setFetchCount(fetchCount); } public void setFetchCount(int fetchCount) { if (fetchCount <= 0) { throw new IllegalArgumentException("Count must be > 0"); } this.fetchCount = fetchCount; } public int getFetchCount() { return fetchCount; } // Some service logic } public TimeLine(int fetchCount) { }
  21. 21. 3. Получить мутантов системы public class TimeLine { private int fetchCount; public TimeLine(int fetchCount) { setFetchCount(fetchCount); } public void setFetchCount(int fetchCount) { if (fetchCount <= 0) { throw new IllegalArgumentException("Count must be > 0"); } this.fetchCount = fetchCount; } public int getFetchCount() { return fetchCount; } // Some service logic } if (fetchCount < 0) { if (fetchCount > 0) {
  22. 22. Итак, как работает мутационное тестирование? 1. Написать тест 2. Выбрать мутации 3. Получить мутантов 5. Пересмотреть тесты 6. Прогнать тесты снова 4. Прогнать тесты на мутантах
  23. 23. 4. Прогнать тесты на мутантах Не покрыто... Как так-то?
  24. 24. Итак, как работает мутационное тестирование? 1. Написать тест 2. Выбрать мутации 3. Получить мутантов 4. Прогнать тесты на мутантах 6. Прогнать тесты снова 5. Пересмотреть тесты
  25. 25. 5. Пересмотреть тесты @BeforeMethod protected void setUp() { timeLine = new TimeLine(10); } @Test public void shouldSetTheConstructorFetchValue() { assertEquals(timeLine.getFetchCount(), 10); } @Test public void shouldUpdateFetchCount() { int expected = 5; timeLine.setFetchCount(expected); assertEquals(timeLine.getFetchCount(), expected); } @Test(expectedExceptions = IllegalArgumentException.class) public void shouldNotAllowNegativeFetchCount() { timeLine.setFetchCount(-10); }
  26. 26. Итак, как работает мутационное тестирование? 1. Написать тест 2. Выбрать мутации 3. Получить мутантов 4. Прогнать тесты на мутантах 5. Пересмотреть тесты 6. Прогнать тесты снова
  27. 27. 6. Прогнать тесты снова
  28. 28. Мутационное тестирование 1. Написать тест Просто пишем обычные тесты безо всяких предположений о том, что будет дальше. 2. Выбрать мутации Код автоматически анализируется и к нему подбираются мутации. 3. Получить мутантов Звучит зловеще, но это тоже происходит автоматически. 4. Прогнать тесты на мутантах Никаких дополнительных действий от программиста тут не требуется – не зря же мы писали тесты на самом первом шаге. 5. Пересмотреть тесты Если мы получили ошибки, либо имеющиеся тесты, либо настройки мутаций надо пересмотреть. 6. Прогнать тесты снова Запустить мутационное тестирование снова, но уже с исправленными тестами/конфигурацией.
  29. 29. ИНСТРУМЕНТЫ Почему PIT?
  30. 30. Jester Nester Pester PIT
  31. 31. БАЙТ-КОД – Работает напрямую с байт-кодом. ДОКУМЕНТАЦИЯ – Хорошая документация + открытый код. – http://www.pitest.org + GitHub ПРОСТОТА – Подсчитывает обычное покрытие строк. – Поддерживает различные оптимизации. PIT
  32. 32. PIT – Пример отчета
  33. 33. PIT – Пример отчета
  34. 34. PIT – Пример отчета
  35. 35. PIT – Пример отчета
  36. 36. PIT – Пример отчета
  37. 37. ▷Стабильные: – простые, – но эффективные. ▷Нестабильные: – мощные, – но чреваты ошибками. PIT – Виды мутаций
  38. 38. ▷Изменение граничных условий PIT – Стабильные мутации if (a < b) {// if (a <= b) // do something }
  39. 39. ▷Изменение граничных условий ▷Инверсия условий PIT – Стабильные мутации if (a == b) {// if (a != b) // do something }
  40. 40. ▷Изменение граничных условий ▷Инверсия условий ▷Инверсия операторов PIT – Стабильные мутации if (a >>> b) {// if (a << b) // do something }
  41. 41. ▷Удаление условий PIT – Нестабильные мутации if (a == b) {// if (true) // do something }
  42. 42. ▷Удаление условий ▷Удаление вызова конструктора PIT – Нестабильные мутации public int foo() { // Object o = null; Object o = new Object(); return o; }
  43. 43. ▷Maven ▷Gradle ▷SonarQube PIT – Интеграция со сборкой
  44. 44. ▷Правильно настраивать плагины сборки. ▷Избегать сгенерированных классов (например, JAXB). ▷Избегать конфликтов со смежными инструментами (например, Clover, Cobertura). С PIT нужно:
  45. 45. ▷Может занимать много времени ▷Сложней реализовать ▷Трудно применить к тестам уровнем выше интеграционных Проблемы мутационного тестирования
  46. 46. Спасибо за внимание! Вопросы?

×