Создание нескольких наборов параметров в одном параметризованном классе (junit)

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

здесь CalculatorTestAdd.java, который имеет набор параметров, которые используются, чтобы проверить, если Add() функция работает правильно. Есть ли у меня возможность "подключить" этот набор к Add() функция и создать дополнительный набор, предназначенный для Subtract() метод и добавьте этот метод в тот же тест класс, в результате чего один файл называется CalculatorTest.java?

6 ответов


да. Ничего особенного делать не надо. Для каждого набора значений параметров каждый метод @Test выполняется один раз, поэтому просто один метод test add() и другой метод test subtract().

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


этот ответ похож на Tarek (параметризованная часть), хотя я думаю, что он немного более расширяемый. Также решает вашу проблему и у вас не будет неудачных тестов, если все правильно:

@RunWith(Parameterized.class)
public class CalculatorTest {
    enum Type {SUBSTRACT, ADD};
    @Parameters
    public static Collection<Object[]> data(){
        return Arrays.asList(new Object[][] {
          {Type.SUBSTRACT, 3.0, 2.0, 1.0},
          {Type.ADD, 23.0, 5.0, 28.0}
        });
    }

    private Type type;
    private Double a, b, expected;

    public CalculatorTest(Type type, Double a, Double b, Double expected){
        this.type = type;
        this.a=a; this.b=b; this.expected=expected;
    }

    @Test
    public void testAdd(){
        Assume.assumeTrue(type == Type.ADD);
        assertEquals(expected, Calculator.add(a, b));
    }

    @Test
    public void testSubstract(){
        Assume.assumeTrue(type == Type.SUBSTRACT);
        assertEquals(expected, Calculator.substract(a, b));
    }
}

Я уверен, что у вас больше нет этой проблемы, но я подумал о 3 способах, которыми вы можете это сделать, каждый со своими плюсами и минусами. С Параметризованным runner вам придется использовать обходной путь.

- использование дополнительных параметров с Параметризованным

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

плюсы: меньше кодирования, и он выполняет все тесты.

минусы: новые параметры для каждого набора тестов.

@RunWith(Parameterized.class)
public class CalculatorTest extends TestCase {
    private Calculator calculator;
    private int operator1;
    private int operator2;
    private int expectedSum;
    private int expectedSub;

    public CalculatorTest(int operator1, int operator2, int expectedSum, int expectedSub) {
        this.operator1 = operator1;
        this.operator2 = operator2;
    }

    @Params
    public static Collection<Object[]> setParameters() {
        Collection<Object[]> params = new ArrayList<>();
        // load the external params here
        // this is an example
        params.add(new Object[] {2, 1, 3, 1});
        params.add(new Object[] {5, 2, 7, 3});

        return params;
    }

    @Before
    public void createCalculator() {
        calculator = new Calculator();
    }

    @Test
    public void addShouldAddTwoNumbers() {
        assertEquals(expectedSum, calculator.add(operator1, operator2));
    }

    @Test
    public void subtractShouldSubtractTwoNumbers() {
        assertEquals(expectedSub, calculator.subtract(operator1, operator2));
    }

    @After
    public void endTest() {
        calculator = null;
        operator1 = null;
        operator2 = null;
        expectedSum = null;
        expectedSub = null;
    }
}

- не используя параметризованный бегун

это отлично работает, если вы задаете свои параметры программно.

плюсы: вы можете иметь столько тестов, сколько хотите, без необходимости устанавливать огромный набор параметров.

минусы: больше кодирования, и он останавливается при первом сбое (который не может быть мошенничеством).

@RunWith(JUnit4.class)
public class CalculatorTest extends TestCase {
    private Calculator calculator;

    @Before
    public void createCalculator() {
        calculator = new Calculator();
    }

    @Test
    public void addShouldAddTwoNumbers() {
        int[] operator1 = {1, 3, 5};
        int[] operator2 = {2, 7, 9};
        int[] expectedResults = {3, 10, 14};

        for (int i = 0; i < operator1.length; i++) {
            int actualResult = calculator.add(operator1[i], operator2[i]);
            assertEquals(expectedResults[i], actualResult);
        }
    }

    @Test
    public void subtractShouldSubtractTwoNumbers() {
        int[] operator1 = {5, 8, 7};
        int[] operator2 = {1, 2, 10};
        int[] expectedResults = {4, 6, -3};

        for (int i = 0; i < operator1.length; i++) {
            int actualResult = calculator.subtract(operator1[i], operator2[i]);
            assertEquals(expectedResults[i], actualResult);
        }
    }

    @After
    public void endTest() {
        calculator = null;
    }
}

- Использование JUnitParams

Я никакой связи с прагматиками, я нашел это несколько дней назад. Эта платформа работает на JUnit и обрабатывает параметризованные тесты по-разному. Параметры передаются непосредственно методу тестирования, поэтому вы можете иметь в одном классе разные параметры для разных методов.

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

минусы: возможно, ваша компания не позволяет добавить новую зависимость к проекту или заставляет вас использовать какое-то странное правило кодирования (например, использовать исключительно параметризованные бегуны). Посмотрим правде в глаза, это случается чаще, чем нам бы хотелось.

здесьпрекрасный пример JUnitParams в действии, и вы можете получить проект/проверить код на этом Github страница.


вы можете использовать параметры с https://github.com/piotrturski/zohhak:

@TestWith({
   "1, 7, 8",
   "2, 9, 11"
})
public void addTest(int number1, int number2, int expectedResult) {
    BigDecimal result = calculator.add(number1, number2);
    assertThat(result).isEqualTo...
}

Если вы хотите загрузить параметры из файла, вы можете использоватьhttp://code.google.com/p/fuzztester/ или http://code.google.com/p/junitparams/

и если вам нужна реальная гибкость, вы можете использовать @параметризованный junit, но он загромождает ваш код. вы также можете использовать теории junit - но это кажется излишним для тестов калькулятора


другое чистое JUnit, но все же элегантное решение, на мой взгляд, заключается в том, чтобы инкапсулировать каждый параметризованный тест(ы) в свой собственный внутренний статический класс и использовать заключенный бегун теста на классе теста верхнего уровня. Это позволяет не только использовать разные значения параметров для каждого теста независимо друг от друга, но и тестировать методы с совершенно разными параметрами.

вот как это будет выглядеть:

@RunWith(Enclosed.class)
public class CalculatorTest {

  @RunWith(Parameterized.class)
  public static class AddTest {

    @Parameters
    public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {
          { 23.0, 5.0, 28.0 }
      });
    }

    private Double a, b, expected;

    public AddTest(Double a, Double b, Double expected) {
      this.a = a;
      this.b = b;
      this.expected = expected;
    }

    @Test
    public void testAdd() {
      assertEquals(expected, Calculator.add(a, b));
    }
  }

  @RunWith(Parameterized.class)
  public static class SubstractTest {

    @Parameters
    public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {
          { 3.0, 2.0, 1.0 }
      });
    }

    @Parameter(0)
    private Double a;
    @Parameter(1)
    private Double b;
    @Parameter(2)
    private Double expected;

    @Test
    public void testSubstract() {
      assertEquals(expected, Calculator.substract(a, b));
    }
  }

  @RunWith(Parameterized.class)
  public static class MethodWithOtherParametersTest {

    @Parameters
    public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {
          { 3.0, 2.0, "OTHER", 1.0 }
      });
    }

    private Double a;
    private BigDecimal b;
    private String other;
    private Double expected;

    public MethodWithOtherParametersTest(Double a, BigDecimal b, String other, Double expected) {
      this.a = a;
      this.b = b;
      this.other = other;
      this.expected = expected;
    }

    @Test
    public void testMethodWithOtherParametersTest() {
      assertEquals(expected, Calculator.methodWithOtherParametersTest(a, b, other));
    }
  }

  public static class OtherNonParameterizedTests {

    // here you can add any other test which is not parameterized

    @Test
    public void otherTest() {
      // test something else
    }
  }
}

обратите внимание на использование @Parameter аннотация в SubstractTest, который я считаю более читабельным. Но это скорее вопрос вкуса.