Определение правильных тестовых примеров jUnit - PullRequest
1 голос
/ 24 апреля 2010

Я новичок в модульном тестировании и поэтому хотел сделать некоторое практическое упражнение, чтобы ознакомиться с фреймворком 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) Каким должен быть идеальный способ проверки метода умножения?

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

Ответы [ 4 ]

4 голосов
/ 24 апреля 2010

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

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");
}
3 голосов
/ 25 апреля 2010

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) Это ПРАВИЛЬНЫЙ способ разработки тестовых случаев? Как я "точно" получаю пользу от этого упражнения?

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

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

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

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

2 голосов
/ 24 апреля 2010

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

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

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

1 голос
/ 24 апреля 2010

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

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

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

...