Именование метода в TDD или BDD, когда выполняется простейшая вещь, которая может работать - PullRequest
2 голосов
/ 19 апреля 2011

Например, мне нужно создать класс Vector, который может возвращать длину векторов.

Сначала я добавляю тест:

@Test
public void shouldReturnLengthOfVector() {
    Vector3D vector = new Vector3D(4d, 2d, -4d);

    assertThat(vector.length(), is(6d));
}

При написании теста создайте класс Vector3D и добавьте заглушку метода.

public double length() {
    // TODO Auto-generated method stub
    return 0;
}

Тест не пройден. Что такое простая вещь, чтобы пройти тест? Твердо закодированное значение:

public double length() {
    return 6d;
}

Тест пройден. Теперь я добавляю метод, который проверяет «угловой регистр»:

@Test
public void someCornercaseShouldReturnLengthOfVector() {
    Vector3D vector = new Vector3D(1d, -2d, -2d);

    assertThat(vector.length(), is(3d));
}

Конечно, это не проходит. Я меняю свою реализацию:

public double length() {
    return Math.sqrt(i * i + j * j + k * k);
}

Все зелено!

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

Ответы [ 5 ]

2 голосов
/ 19 апреля 2011

Самое простое, что может сработать, - это добавить еще одно утверждение к shouldReturnLengthOfVector:

@Test
public void shouldReturnLengthOfVector() {
    Vector3D v1= new Vector3D(4d, 2d, -4d);
    assertThat(v1.length(), is(6d));

    Vector3D v2 = new Vector3D(1d, -2d, -2d);
    assertThat(v2.length(), is(3d));
}

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

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

1 голос
/ 19 апреля 2011

Вы также можете изменить свой тестовый код.someCornercaseShouldReturnLengthOfVector - это абсолютно правильное имя, пока вы находитесь на стадии «самая простая вещь, которая может работать».Измените имя, чтобы оно отражало то, что на самом деле тестирует код, когда вы продолжите тестирование.

Вы также можете комментировать свой тестовый код, чтобы сделать его намерение более ясным;)

1 голос
/ 19 апреля 2011

Нет модульного теста для; Понятно ли значение этого метода? Вы должны использовать свое суждение.

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

0 голосов
/ 19 апреля 2011

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

0 голосов
/ 19 апреля 2011

Я следую следующей схеме, когда называю свои методы:

WhatImTesting_WhatAreTheImputs_ExpectedResult

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

В другом примере предположим, что я хотел проверить следующий конструктор:

public class House
{
    Door theDoor;
    public House(Door aDoor)
    {
        if(aDoor == null)
        {
            throw new IllegalArgumentException();
        }
        theDoor = aDoor;
    }
}

Возможно, у меня есть два способа проверить это:

  • Constructor_ValidDoor_ObjectCreated(): Это будет проверять, что объект House создан, когда параметр конструктора действителен.
  • Constructor_NullDoor_ExceptionThrown(): Это будет проверять, что исключение выдается, когда нулевой параметр передается в конструктор.
...