JUnit, что утверждает, я должен использовать - PullRequest
0 голосов
/ 27 декабря 2018

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

public boolean arrayListEmpty()
    {
        if(numericalSequence.isEmpty() == true)
            return true;
        else
            return false;
    }

Это публичный метод из модели, который, я полагаю, я должен проверить, он просто возвращает true, если моя числовая последовательность пуста, как вы можете видеть.Я не могу проверить это напрямую, вызывая numericSequence.isEmpty (в контроллере, где он мне нужен), потому что он закрытый.Итак, очевидная вещь - это проверить

assertEquals(true, test.arrayListEmpty());

Так что мой вопрос касается предложений, какие другие утверждения я должен использовать / какие случаи я должен предсказать, какие могут выйти.Должен ли я в методе Test заполнить numericSequence некоторыми значениями и также подтвердить это?(для меня это не обязательно, потому что любое значение, вставленное в последовательность = не нуль, но, возможно, это не так просто)

1 Ответ

0 голосов
/ 27 декабря 2018

Прежде всего, добро пожаловать в Stack Overflow!

Глядя на ваш вопрос, звучит так, будто вы новичок в юнит-тестировании (поправьте меня, если я ошибаюсь).Итак, я разделю свои ответы на два раздела;(1) ответить на ваш вопрос и (2) дать общее руководство о том, как писать хорошие тесты и тестируемые классы.

1.Отвечая на ваш вопрос

Есть еще несколько вариантов использования, о которых вы можете подумать здесь:

  1. Что произойдет, если numericalSequence равно null?
  2. Что, если numericalSequence имеет 1 элемент?
  3. Что если numericalSequence имеет нулевой элемент?

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

2.Написание хороших тестов

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

ПРИМЕЧАНИЕ. Это не исчерпывающее руководство, но оно предназначено для того, чтобы начать путь с написания лучшего кода и лучших тестов

Итак, предположим, что класс, который нужно протестировать, написан так:

class MyClass {
  // NOTE: This is not `final`
  private List<Integer> numericalSequence;

  public MyClass() {
    this.numericalSequence = new ArrayList<>();
  }

  public void doSomething(Integer x) {
    if (x < 0) {
      numericalSequence = new ArrayList<>();
    } else {
      numericalSequence.add(2 * x);
    }
  }

  public boolean arrayListEmpty() {
    // NOTE: Your sample code can be reduced to this one-liner
    return numericalSequence.isEmpty();
  }
}

Вот некоторые недостатки в приведенном выше коде:

  1. doSomething методдопускает значения NULL (целые в штучной упаковке) и может вызывать NullPointerException в первом операторе if.
  2. Элемент numericalSequence не является окончательным, и, следовательно, код, который устанавливает его в null, действителен внутриметод doSomething
  3. Метод arrayListIsEmpty не проверяет, является ли numericalSequence нулевым
  4. Если я хочу проверить, как arrayListIsEmpty ведет себя, когда numericalSequence является нулевым или имеетпустые элементы, это трудно сделать, если вы не знаете, как перевести класс в это состояние.

Если класс был переписан следующим образом:

class MyClass {
  private final List<Integer> numericalSequence;

  public MyClass() {
    this(new ArrayList<>());
  }

  // Should be made public only if the classes that use this one needs to
  // initialize this instance with the sequence. Make this package-private
  // otherwise.
  public MyClass(List<Integer> sequence) {
    this.numericalSequence = sequence;
  }

  public void doSomething(int x) {
    if (x < 0) {
      // COMPILE ERROR: Cannot assign to a final member
      // numericalSequence = new ArrayList<>();
      numericalSequence.clear();
    } else {
      numericalSequence.add(2 * x);
    }
  }

  public boolean arrayListEmpty() {
    return numericalSequence == null || numericalSequence.isEmpty();
  }
}

Несколько замечаний по поводу вышеуказанной структуры:

  1. Есть два конструктора;по умолчанию вызывается тот, который принимает список целых чисел в качестве последовательности, так что он использует любую логику, которой оба должны были бы поделиться.В этом примере нет логики, но, надеюсь, вы скоро встретите одну из них.
  2. Метод doSomething() не принимает значение Integer, но значение int гарантирует, что xникогда не бывает null (типы числовых примитивов Java не могут быть null).Это также означает, что numericalSequence не может содержать нулевые значения через doSomething().
  3. Поскольку numericalSequence можно инициализировать извне этого класса, метод arrayListEmpty() гарантирует, что numericalSequence либоnull действительно пуст.

Теперь вы можете писать тестовые примеры, например, так:

@Test
public void arrayListEmpty_WhenListIsNull() {
  MyClass test = MyClass(null);
  assertTrue(test.arrayListEmpty());
}

@Test
public void arrayListEmpty_WhenListIsEmpty() {
  MyClass test = MyClass();
  assertTrue(test.arrayListEmpty());
}

@Test
public void arrayListEmpty_WhenListHasOnlyOneNonNullElement() {
  List<Integer> sequence = new ArrayList<>();
  sequence.add(0);
  MyClass test = new MyClass(sequence);
  assertFalse(test.arrayListEmpty());
}

@Test
public void arrayListEmpty_WhenListHasOnlyOneNullElement() {
  List<Integer> sequence = new ArrayList<>();
  sequence.add(null);
  MyClass test = new MyClass(sequence);
  assertFalse(test.arrayListEmpty());
}

Поскольку doSomething() добавляет / очищает последовательность при написании тестов для doSomething() убедитесь, что вызов и проверить состояние класса, проверив возвращаемое значение arrayListEmpty().

Например:

@Test
public void doSomething_WhenInputLessThanZero() {
  List<Integer> sequence = new ArrayList<>();
  sequence.add(0);
  MyClass test = new MyClass(sequence);
  test.doSomething(-1);
  assertTrue(test.arrayListEmpty());
}

Я намеревался показать пару вещей:

  1. Структурируйте свои тестовые задания так, чтобы они были небольшими и лаконичными
  2. Сделайте так, чтобы ваш класс легко тестировался

Надеюсь, это поможет.

...