Можно ли использовать в модульном тесте методы класса, не прошедшего тестирование, для настройки теста? - PullRequest
1 голос
/ 17 октября 2019

У меня есть класс Inventory, который имеет 6 методов. Я должен реализовать тесты для каждого из этих 6 методов в тестовом классе InventoryTEST. Объект класса является хэш-картой.

Вот методы для класса

 /**
   * Return the number of Records.
   */
  public int size() { }

  /**
   * Return a copy of the record for a given Video.
   */
  public Record get(VideoObj v) {  }

  /**
   * Return a copy of the records as a collection.
   * Neither the underlying collection, nor the actual records are returned.
   */
  public Collection toCollection() {}

  /**
   * Add or remove copies of a video from the inventory.
   * If a video record is not already present (and change is
   * positive), a record is created. 
   * If a record is already present, <code>numOwned</code> is
   * modified using <code>change</code>.
   * If <code>change</code> brings the number of copies to be less
   * than one, the record is removed from the inventory.
   * @param video the video to be added.
   * @param change the number of copies to add (or remove if negative).
   * @throws IllegalArgumentException if video null or change is zero
   * @postcondition changes the record for the video
   */
  public void addNumOwned(VideoObj video, int change) {

  }

  /**
   * Check out a video.
   * @param video the video to be checked out.
   * @throws IllegalArgumentException if video has no record or numOut
   * equals numOwned.
   * @postcondition changes the record for the video
   */
  public void checkOut(VideoObj video) {
  }

  /**
   * Check in a video.
   * @param video the video to be checked in.
   * @throws IllegalArgumentException if video has no record or numOut
   * non-positive.
   * @postcondition changes the record for the video
   */
  public void checkIn(VideoObj video) {

  }

  /**
   * Remove all records from the inventory.
   * @postcondition <code>size() == 0</code>
   */
  public void clear() {

  }

Теперь, чтобы протестировать эти методы, мне нужно будет создать объект с некоторыми записями в нем. Один из способов сделать это - вызвать конструктор по умолчанию, который даст мне пустую хэш-карту, а затем вызвать addNumOwned, чтобы добавить записи в хеш-карту. Другой способ сделать это - создать перегруженный конструктор, который может добавлять записи в хэш-карту во время создания.

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

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

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

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

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

public ThingTest // We have a class named Thing we want to test, this is its unit tests
{

   @Test
   public void testIncrement() // Test of the Thing.increment method
   {
      // Set up:
      var thing = new Thing(); // Using part of the Thing class in the set up phase!

      // Exercise:
      thing.increment();

      // Verify:
      assertEquals(1, thing.count());
   }
...

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

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

Для сложного кода вы можете рассмотреть возможность использования уровня Java assert утверждения (мои предпочтения) или предположения JUnit , чтобы проверить, что фаза настройки теста завершена правильно, прежде чем приступить к выполнению тестируемого вами метода. Тогда вместо трудной отладки неудачного теста вы получите AssertionError или AssumptionViolatedException или TestAbortedException, который более четко указывает напричина проблемы.

   @Test
   public void testIncrement()
   {
      var thing = new Thing();
      assert thing.count() == 0;

      thing.increment();

      // Verify:
      assertEquals(1, thing.count());
   }
...
1 голос
/ 17 октября 2019

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

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

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

По всем вопросам, пожалуйста, дайте мнезнаю.

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