4. ЯКІСТЬ ТЕСТІВ ЯК ОСНОВА
ЯКОСТІ КОДУ
Яким же чином я можу оцінити якість тестів?
5. ЯК?
Ніяк! Просто використовуй TDD, цього достатньо!
Потрібно проводити регулярні рев’ю коду тестів
Постійно вимірювати і збільшувати тестове покриття
Точно, чим більше покриття, тим кращі наші тести
• line coverage
• statement coverage
• branch coverage
• ….
6. public class Item
{
private int quantity;
public int getStrangeQuantity()
{
return (quantity <= 0) ? 0 : 10;
}
public void addItem(int value)
{
quantity = value;
}
public void resetItem()
{
quantity = 0;
}
}
public void addItem(int value)
{
quantity = value;
}
public void resetItem()
{
quantity = 0;
}
public int getStrangeQuantity()
{
return (quantity <= 0) ? 0 : 10;
}
7. public class ItemTest
{
Item item = new Item();
@Test
public void testLessThenZerro()
{
item.addItem(-10);
assertEquals(0, item.getStrangeQuantity());
}
@Test
public void testMoreThanZerro()
{
item.addItem(5);
assertEquals(10, item.getStrangeQuantity());
}
}
@Test
public void testLessThenZero()
{
item.addItem(-10);
assertEquals(0, item.getStrangeQuantity());
}
@Test
public void testMoreThanZero()
{
item.addItem(5);
assertEquals(10, item.getStrangeQuantity());
}
8. public class Item
{
private int quantity;
public int getStrangeQuantity()
{
return (quantity <= 0) ? 0 : 10;
}
public void addItem(int value)
{
quantity = value;
}
public void resetItem()
{
quantity = 0;
}
}
9. public class Item
{
private int quantity;
public int getStrangeQuantity()
{
return (quantity < 0) ? 0 : 10;
}
public void addItem(int value)
{
quantity = value;
}
public void resetItem()
{
quantity = 0;
}
}
// change < to <=
10. public class ItemTest
{
Item item = new Item();
@Test
public void testLessThenZero()
{
item.addItem(-10);
assertEquals(0, item.getStrangeQuantity());
}
@Test
public void testMoreThanZero()
{
item.addItem(5);
assertEquals(10, item.getStrangeQuantity());
}
}
11. public class ItemTest
{
Item item = new Item();
@Test
public void testLessThenZero()
{
item.addItem(-10);
assertEquals(0, item.getStrangeQuantity());
}
@Test
public void testMoreThanZero()
{
item.addItem(5);
assertEquals(10, item.getStrangeQuantity());
}
@Test
public void testEqualZero()
{
item.addItem(0);
assertEquals(0, item.getStrangeQuantity());
}
}
<-----
12. public class ItemTest
{
Item item = new Item();
@Test
public void testAddItems()
{
item.addItem(-5);
item.addItem(5);
item.addItem(0);
}
@Test
public void testResetItem()
{
item.resetItem();
assertEquals(0, item.getStrangeQuantity());
}
}
Покриття 100% !!!
17. ПРОБЛЕМА ВІЧНО ЖИВИХ
МУТАНТІВ
public void makeSomething(int value){
if (value <= 10){
throw new IllegalArgumentexception();
}
if (value >= 10){
executeSomeLogic();
}
}
public void makeSomething(int value){
if (value <= 10){
throw new IllegalArgumentexception();
}
if (value > 10){
executeSomeLogic();
}
}
public void makeSomething(int value){
if (value <= 10){
throw new IllegalArgumentexception();
}
executeSomeLogic();
}
18. ПРОБЛЕМА ВІЧНО ЖИВИХ
МУТАНТІВ
public int makeSomething(){
int value;
value=0;
....
....
return value++;
}
public int makeSomething(){
int value;
value=0;
....
....
return value++;
}
19. ЕКВІВАЛЕНТНІ МУТАЦІЇ
Безглуздий або мертвий код
Впливають тільки на швидкодію
Не можуть бути викликані згідно існуючої
логіки виконання
Змінюють тільки внутрішній стан класу
24. АБСОЛЮТНО НЕПРИЙНЯТНІ
ВИТРАТИ ЧАСУ
Використаємо 10 типів мутаційних операторів
Нехай буде згенеровано 10000 мутантів
Припустимо, що мутант компілюється за 1 секунду
2.5 години тільки на генерацію мутантів
Запустимо тести 10000 разів
25 годин
25 ГОДИН!
25. ЩО РОБИТИ?
Не мутувати код напряму щоб уникнути перекомпіляції
Генерувати мутантів прямо в байт коді (ASM, BCEL)
Підключити здоровий глузд
Не мутувати той код, який не покритий тестами
Не запускати ті тести, які не тестуют мутований код
Використовувати паралелізм
Використовувати інкрементальний аналіз
26. СУЧАСНІ СИСТЕМИ
Генерація мутантів – код, BCEL, ASM
Вибір мутантів – вручну, все підряд, за певними умовами,
враховуючи покриття
Дететкція мутантів – прогон всіх тестів, селекція і ранній вихід
Предствлення результів – звичайний текст, форматований
текст, підсвітка коду
Структурований формат – так, ні
Підтримка тестових фреймворків – TestNG, Junit
Підтримка мок фреймворків – Mickito, Powermock, EasyMock,
Jmock і т.п.
Підтримка білд систем – Ant, Maven
27. Генерація Вибір Детекція Звіт СФ Тест Мок Білд
Jester код все всі код ні Junit ні ні
Simple Jester код все всі код ні Junit ні ні
Jumble BCEL умови РВ текст ні Junit так ant
PIT ASM покриття РВ код так так так так
µ Java код вручну ні код ні ні ні ні
javaLanche ASM покриття РВ ф.текст так Junit ні ні
СУЧАСНІ СИСТЕМИ
http://pitest.org/java_mutation_testing_systems/
How can I SAFELY refactor the code?
How can I SAFELY refactor the code of the test?
How can I TRUST to my test suite?
How can I ensure that my TEAM write effective tests?
How can I retrofitted my tests to test old legacy code?
How do I assess the quality of a test suit?
Don’t worry! USE TDD. Do code Review. Increase coverage. Etc.
Coverage – lines, statement, branch etc… NONE of those can’t tell you that your code was tested! It only shows the code which was NOT Tested.
Executing is not the same as testing.
Sometimes help to find redundant code
But usually not, so required manual investigation
This is a PROBLEM as far as if killed – your are ok
But is survived – it can be equivalent and require manual investigation