Подтвердить что ты не робот

Тестируемая разработка - как написать тест, прежде чем ни один из кода реализации не существует

Я изучаю TDD, но изо всех сил стараюсь принять его, поскольку это не просто.

Вопрос, на который я не могу ответить, " Как написать тест до того, как существует какой-либо код реализации?".

Если тип целевого класса/целевого метода/целевого типа/целевого типа возврата не существует,

  • На что мы ссылаемся при написании кода в тесте. Как начать запись теста?
  • Как прошел тест, если все, что мы могли написать, это просто имя метода теста до фактического кода реализации?

Все говорят WHY, но не HOW

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

Пример использования.

Предположим, что мы разрабатываем программное обеспечение для Университета, и наш прецедент - это регистрация курса.

Чтобы это было просто, давайте ограничимся этим обсуждением

  • : "Студент может зарегистрироваться максимум на 3 курса за семестр"
  • тестовый сервисный уровень и уровень dao.

псевдокод

ENROLL(studentId, courseId)
    //check if student enrolled in less than 3 courses in the same semester as given courseId belongs in.
    //if yes, enroll him/her.
    //if not, return an error.

Фактическая реализация выше может охватывать пару классов, включающих службы, daos и т.д.

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

Я надеюсь, что это может помочь во многих битвах, подобных мне в будущем.

4b9b3361

Ответ 1

Создайте класс EnrollingServiceTest в src/test/java в том же пакете, что и для EnrollingService

class EnrollingServiceTest {
    private EnrollingService enrollingService;

    @Before 
    public void init() {
           enrollingService = new EnrollingService();
    }

    @Test
    public void testEnroll() {
           boolean result = enrollingService.enroll(1l, 1l);
           assertTrue(result);
    ...

IDE (я предполагаю, что вы используете IDE) показывает ошибки - EnrollingService не существует.

Наведите курсор на EnrollService - IDE предложит создать класс - пусть он будет создан в src/main/java

Теперь IDE говорит, что отсутствует метод регистрации (длинный, длинный) - пусть IDE создаст его для вас.

Теперь IDE не показывает ошибок. Запустите тест - он терпит неудачу. Пойдите, чтобы зарегистрировать и начать реализацию логики

И так далее...

Ответ 2

Это станет яснее, когда вы сосредоточитесь на ожидаемом поведении кода, а не на реализации кода. Поэтому, учитывая описанный вами сценарий, вы можете прийти к выводу, что вам придется написать метод enroll() в каком-то классе. Затем вы можете рассмотреть, как вы собираетесь тестировать этот класс.

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

Итак, беря выражение: студент может зарегистрироваться максимум на 3 курса за семестр, вы можете подумать о том, как это может произойти.

  • Студент зарегистрирован на 0 курсов за данный семестр, пытается зарегистрироваться на курс, результат: регистрация успешна; студент теперь зарегистрирован на 1 курс за данный семестр.
  • Студент зарегистрирован на 1 курс в течение данного семестра, пытается зарегистрироваться на курс, результат: регистрация успешна; студент теперь зарегистрирован на 2 курса за данный семестр.
  • Студент зарегистрирован на 3 курса для данного семестра, пытается зарегистрироваться на курс, результат: Неудача (может быть, исключение выбрано?)
  • и т.д.

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

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

Ответ 3

public void shouldNotEnrollInMoreThanFourClassesInASemester() {
  Enroller enroller = new Enroller();
  Student student = new Student();
  Semester one = new Semester();
  Semester two = new Semester();
  Course geology = new Course(one);
  Course architecture = new Course(one);
  Course calculus = new Course(one);
  Course sociology = new Course(one);
  Course geometry = new Course(two);

  assertOk(enroller.enroll(student, geology));
  assertOk(enroller.enroll(student, architecture));
  assertOk(enroller.enroll(student, calculus));
  assertNotOk(enroller.enroll(student, sociology));
  assertOk(enroller.enroll(student, geometry));
}

Ответ 4

В вашем сценарии вы должны протестировать каждый слой отдельно, так что извините dao при тестировании уровня сервиса.

Когда вы впервые пишете тест, он не будет компилироваться, что означает, что он терпит неудачу, но это нормально, поскольку классы не существуют.

В вашем примере, какой уровень должен быть установлен для регистрации не более 3 курсов? Это повлияет на то, как вы тестируете.

Написание теста сначала поможет вам справиться с этими типами вопросов.

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

Итак, напишите свой тест dao, затем напишите классы и методы, чтобы он компилировался, но он все равно должен завершиться неудачей, пока yiu не завершит реализацию. Вероятно, вы захотите проверить регистрацию на 2,3,4 класса и обеспечить, чтобы каждый из них был неудачным, а затем завершил реализацию.