Это мой первый пост на 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) } }) } }
Из вышесказанного есть три изменения, давайте рассмотрим их по отдельности:
хочу ошибиться ошибка
- мы меняем это с
bool
чтобы мы могли провести сравнение с ошибкой, возвращаемой функцией
- мы меняем это с
wantErr: ошибки. Новое ("у собаки не может быть символов в имени"),
- это структура ошибки, которая мы ожидаем
если 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.
Ознакомьтесь с go tests и скопируйте каталог шаблонов в выбранное вами место
клон git https://github.com/cweill/gotests.git
cp -R gotests/internal/render/templates ~/scratch/go тесты
Перепишите содержимое function.tmpl с помощью содержимого этого Gist
Добавьте следующий параметр в настройки VSCode.json
""go.generateTestsFlags": ["--template_dir=~/scratch/templates"]
Как только вы это сделаете, будущие тесты теперь будут генерироваться с более строгим тестированием на ошибки! 🎉
Я понимаю, что приведенные выше рекомендации сделают ваш код более хрупким, поскольку код подвержен любому изменению сообщения об ошибке, скажем, нижестоящей библиотеки. Однако для себя я предпочитаю писать тесты, которые являются строгими и минимизируют вероятность других ошибок, загрязняющих тесты.
Я также понимаю, что GoodestBoy # 1, вероятно, является подходящим именем для собаки! 🐶
Оригинал: “https://dev.to/jdheyburn/extending-gotests-for-strict-error-tests-4j96”