2010-04-24 3 views
1

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

Я создал программу, которая реализует строкового множитель

public String multiply(String number1, String number2) 

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

public class MultiplierTest { 
    @Test 
    public void testMultiply() { 
     Multiplier multiplier = new Multiplier(); 
     // Test for 2 positive integers 
     assertEquals("Result", 5, multiplier.multiply("5", "1")); 

     // Test for 1 positive integer and 0 
     assertEquals("Result", 0, multiplier.multiply("5", "0")); 

     // Test for 1 positive and 1 negative integer 
     assertEquals("Result", -1, multiplier.multiply("-1", "1")); 

     // Test for 2 negative integers 
     assertEquals("Result", 10, multiplier.multiply("-5", "-2")); 

     // Test for 1 positive integer and 1 non number 
     assertEquals("Result", , multiplier.multiply("x", "1")); 

     // Test for 1 positive integer and 1 empty field 
     assertEquals("Result", , multiplier.multiply("5", "")); 

     // Test for 2 empty fields 
     assertEquals("Result", , multiplier.multiply("", "")); 
    } 
} 

Аналогичным образом я могу создавать тестовые примеры, связанные с граничными случаями (с учетом чисел int) или даже мнимых значений.

1) Но что должно быть ожидаемым значением для последних 3 тестовых примеров выше? (специальное число с указанием ошибки?)

2) Какие дополнительные тестовые примеры я пропустил?

3) Является ли assertEquals() метод достаточно для тестирования метод множителей или мне нужны другие методы, такие как assertTrue(), assertFalse(), assertSame() и т.д.

4) Является ли это правильный путь идти о разработка тестов? Как я «точно» извлекаю выгоду из этого упражнения?

5) Какой должен быть идеальный способ тестирования метода множителя?

Я довольно невежественный здесь. Если кто-то может ответить на эти вопросы, я бы очень признателен. Спасибо.

+0

Просто мелочь - все ваши тесты имеют «Результат» в виде строки. Эта строка должна быть информативной - в первой, например, вы можете вместо этого сказать «5 * 1! = 5». –

+0

Это 5 вопросов, а не 1, – Raedwald

ответ

3

1) Но что должно быть ожидаемым значением для последних 3 тестовых примеров выше? (специальный номер, указывающий на ошибку?)

Как объяснили другие ответчики, это зависит от договора интерфейса вашего множителя. Вам следует подумать о том, как вы (или его клиенты в целом) должны использовать его, что должно произойти в случае конкретных ошибок или крайних случаев и т. Д. В Java соглашение должно вызывать исключение в таких случаях.

2) Какие дополнительные тестовые примеры я пропустил?

Несколько случаев, которые приходят на ум:

// test commutativity 
assertEquals("0", multiplier.multiply("0", "5")); 
assertEquals("-1", multiplier.multiply("1", "-1")); 
assertEquals("149645", multiplier.multiply("173", "865")); 
assertEquals("149645", multiplier.multiply("865", "173")); 

// test some more unusual cases of multiplying with 0 
assertEquals("0", multiplier.multiply("-5", "0")); 
assertEquals("0", multiplier.multiply("0", "-0")); 
// test with numbers starting with '+' 
assertEquals("368", multiplier.multiply("+23", "+16")); 
assertEquals("-368", multiplier.multiply("-23", "+16")); 

// test multiplying huge values without overflow 
assertEquals("18446744073709551616", multiplier.multiply("4294967296", "4294967296")); 
assertEquals("18446744073709551616", multiplier.multiply("-4294967296", "-4294967296")); 

3) assertEquals() метод достаточно для тестирования метод множителей или мне нужны другие методы, такие как assertTrue(), assertFalse(), assertSame() и т. д.

В этом случае все, что вам нужно, это сравнить два значения для равенства. В других тестах вам могут потребоваться разные виды утверждений.

4) Является ли это ПРАВИЛЬНЫМ способом разработки тестовых случаев? Как я «точно» извлекаю выгоду из этого упражнения?

Нет единого «правильного» способа модульного тестирования. Самое близкое, вероятно, test driven development, которое рекомендуется многими (включая меня), если вы пишете свой код с нуля.

Ваша польза от этого упражнения, вероятно, в том, что вы знакомы с JUnit и некоторое время пытались «шляпу тестера».

5) Какой должен быть идеальный способ тестирования метода множителя?

Как этот вопрос отличается от предыдущего?

+0

Спасибо за указатели. Теперь это имеет смысл. – Epitaph

+0

Можно ли использовать один метод, содержащий несколько assertEquals() для подобных тестовых примеров? Например, имея 1 метод testArgumentMultiply() для тестовых случаев, содержащих незаконные входы, такие как символы, специальный символ, строки, пустую строку. Поскольку все эти входы приведут к тому же исключению NumberFormatException? – Epitaph

+0

@ Epitaph, пуристы настаивают на том, что в любом методе тестирования следует проверять только одну вещь. Я не такой разборчивый. Я стараюсь проверить один последовательный пример использования в методе тестирования, включая, возможно, несколько утверждений. В вашем конкретном случае, однако, обратите внимание, что при вызове метода, вызывающего исключение, выполнение метода вызывающего теста завершается там, поэтому дальнейшие вызовы не будут выполняться. Другими словами, вы должны поместить каждый из ваших тестов исключения в свой отдельный метод тестирования. –

4

Во-первых, ваш код находится в ошибке, потому что у вас есть класс, но нет функций. Я предполагаю, что все эти тесты находятся в одной функции? Если так, я бы посоветовал это сделать. Как правило, вы хотите один тест, чтобы проверить одну вещь так:

public class MultiplierTests { 
    @Test 
    public void testSimpleMultiple() { 
    assertEquals(...); 
    } 

    ... 
} 

Во-вторых, вы пропускании Int как результат здесь:

assertEquals("Result", 5, multiplier.multiply("5", "1")); 

но Multiplier.multiply() возвращает String?

Итак, как вы тестируете это, зависит от результата. Если он передан в пустой строке, он генерирует исключение? В этом случае вы можете определить @Test аннотации сказать, что ожидает, что исключение будет брошено:

@Test(expected = IllegalArgumentException.class) 
public void test() { 
    multiplier.multiply("", "5"); 
} 
+0

В вашем примере IllegalArgumentException, что должно идти в области ожидаемого значения, если я использую метод assertEquals() с тремя параметрами, как показано ниже: @Test (expected = NumberFormatException.class) public void testMultiply() { assertEquals ("4 * a",?, tester.multiply ("3", "a"); } – Epitaph

+0

@Epitaph в примере 'IllegalArgumentException', не используйте' assertEquals() 'Просто вызовите метод. Если исключение не будет выбрано, тест завершится неудачно.Если выбрано исключение, отличное от 'IllegalArgumentException', тест завершится с ошибкой. Он будет передан только в том случае, если выбрано 'IllegalArgumentException'. – cletus

+0

Спасибо. Я попытался ввести «новое NumberFormatException()» для ожидаемого значения, и он сработал. Это тоже хорошо? – Epitaph

2

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

Хороший способ определить, пропустили ли вы какие-либо случаи в сложных методах, - запустить их через инструмент покрытия кода. Запустите все ваши тесты, а затем посмотрите на результат покрытия кода. Если есть части вашего кода, которые не посещаются вашими тестовыми примерами, возможно, вам не хватает некоторых из них.

Вы можете найти хорошее руководство here.

+0

Вы можете порекомендовать некоторые инструменты для покрытия кода? – Carl

+0

Здесь есть хороший список: http://java-source.net/open-source/code-coverage. Я предлагаю вам попробовать http://codecover.org/ Я лично использую Clover из Atlassian, но это не бесплатный инструмент. – Prachi

1

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

@Test(expected= NumberFormatException.class) 
public void test() { 
    multiplier.multiply("a", "b"); 
} 

Я не согласен с Клетусом по его реализации, так как его тестовый пример ожидает все охватывающего IllegalArgumentException, я думаю, что лучше тестировать определенные подкласс, чем использовать родительское исключение.

+0

Я считаю, что 'IllegalArgumentException' должен был быть только примером. –

+0

Я признаю этот момент, но факт ожидает, что родительское исключение может заставить вас уловить множество других неожиданных исключений. – Kartik

Смежные вопросы