Рубрики
Без рубрики

Расширение тестов Go для строгих тестов на ошибки

Здесь я описываю пользовательский шаблон, используемый для улучшения проверки ошибок в библиотеке forests. С пометкой go, java, тестирование.

Это мой первый пост на dev.to , X-опубликовано в моем новом личном блоге которые можно найти здесь . Надеюсь, у меня будет dev.to публикация из RSS кормит, как только я с этим разберусь!

Будем рады получить любую обратную связь, которая у вас может возникнуть! 😃

Мне нравится подтверждать стабильность моего кода с помощью написания тестов и практики разработки на основе тестирования (TDD). Для Java JUnit был моим предпочтительным фреймворком тестирования. При написании тестов для подтверждения возникновения исключения я использовал необязательный параметр expected для аннотации @Test , однако я быстро обнаружил, что это решение не будет работать для методов, в которых я несколько раз вызывал один и тот же класс исключений для разных сообщений об ошибках, и тестирование на эти сообщения.

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

public static boolean validateDogName(String dogName) throws DogValidationException {

    if (containsSymbols(dogName)) {
        throw new DogValidationException("Dogs cannot have symbols in their name!");
    }

    if (dogName.length > 100) {
        throw new DogValidationException("Who has a name for a dog that long?!");
    }

    return true;
}

Для этого метода просто используйте @Test(expected.class )

Чтобы решить эту проблему, я наткнулся на класс ExpectedException для JUnit в Baeldung , который позволяет нам указать ожидаемое сообщение об ошибке. Здесь он применяется к тестовому варианту для этого метода:

@Rule
public ExpectedException exceptionRule = ExpectedException.none();

@Test
public void shouldHandleDogNameWithSymbols() {
    exceptionRule.expect(DogValidationException.class);
    exceptionRule.expectMessage("Dogs cannot have symbols in their name!");
    validateDogName("GoodestBoy#1");
}

Возвращаясь к Golang, отметим, что существует встроенная библиотека с метким названием testing , которая позволяет нам утверждать условия тестирования. В сочетании с Go tests – инструментом для создания Go-тестов из вашего кода – написание тестов не может быть проще! Мне нравится, как это сочетается с расширением Go для VS Code, моим любимым текстовым редактором (на данный момент …).

Преобразование вышеупомянутого Java validatetagname метод для Golang выдаст что-то вроде:

func validateDogName(name string) (bool, error) {
    if containsSymbols(name) {
        return false, errors.New("dog cannot have symbols in their name")
    }

    if len(name) > 100 {
        return false, errors.New("who has a name for a dog that long")
    }

    return true, nil
}

Если у вас есть метод Go, который возвращает интерфейс error , то go tests сгенерирует тест, который будет выглядеть следующим образом:

func Test_validateDogName(t *testing.T) {
    type args struct {
        name string
    }
    tests := []struct {
        name    string
        args    args
        want    bool
        wantErr bool
    }{
        name: "Test error was thrown for dog name with symbols",
        args: args{
            name: "GoodestBoy#1",
        },
        want: false,
        wantErr: true,
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := validateDogName(tt.args.name)
            if (err != nil) != tt.wantErr {
                t.Errorf("validateDogName() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if got != tt.want {
                t.Errorf("validateDogName() = %v, want %v", got, tt.want)
            }
        })
    }
}

Исходя из вышесказанного, мы ограничены тем, какую ошибку мы можем утверждать, здесь любая возвращенная ошибка пройдет проверку. Это эквивалентно использованию @Test(expected=Exception.class ) в JUnit! Но есть и другой способ…

Изменение сгенерированного теста

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

func Test_validateDogName(t *testing.T) {
    type args struct {
        name string
    }
    tests := []struct {
        name    string
        args    args
        want    bool
        wantErr error
    }{
        name: "Test error was thrown for dog name with symbols",
        args: args{
            name: "GoodestBoy#1",
        },
        want: false,
        wantErr: errors.New("dog cannot have symbols in their name"),
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := validateDogName(tt.args.name)
            if tt.wantErr != nil && !reflect.DeepEqual(err, tt.wantErr) {
                t.Errorf("validateDogName() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if got != tt.want {
                t.Errorf("validateDogName() = %v, want %v", got, tt.want)
            }
        })
    }
}

Из вышесказанного есть три изменения, давайте рассмотрим их по отдельности:

  1. хочу ошибиться ошибка
    • мы меняем это с bool чтобы мы могли провести сравнение с ошибкой, возвращаемой функцией
  2. wantErr: ошибки. Новое ("у собаки не может быть символов в имени"),
    • это структура ошибки, которая мы ожидаем
  3. если tt.wantErr && !отразит. deepEqual(ошибка, т.е.wantErr) {
    • проверьте, чтобы убедиться, что в тесте ожидается ошибка, если это так, то сравните ее с возвращенной ошибкой

Пункт 3 обеспечивает дополнительную поддержку, если был тестовый пример, который не ожидал ошибки. Обратите внимание, что water полностью исключен из приведенного ниже тестового примера.

{
    name: "Should return true for valid dog name",
    args: args{
        name: "Benedict Cumberland the Sausage Dog",
    },
    want: true,
}

Настройка тестов Сгенерированный тест

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

  1. Ознакомьтесь с go tests и скопируйте каталог шаблонов в выбранное вами место

    • клон git https://github.com/cweill/gotests.git
    • cp -R gotests/internal/render/templates ~/scratch/go тесты
  2. Перепишите содержимое function.tmpl с помощью содержимого этого Gist

  3. Добавьте следующий параметр в настройки VSCode.json

    • ""go.generateTestsFlags": ["--template_dir=~/scratch/templates"]

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

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

Я также понимаю, что GoodestBoy # 1, вероятно, является подходящим именем для собаки! 🐶

Оригинал: “https://dev.to/jdheyburn/extending-gotests-for-strict-error-tests-4j96”