Тестовые обратные вызовы, такие как beforeEach

Я хочу выполнить модульные тесты над структурой, которую я закодировал в golang. Однако у меня есть повторяющиеся задачи, которые я не хочу каждый раз явно повторять вручную. Тем не менее, мне нравится помещать их в функцию BeforeEach, а затем заставлять каждый тест выполнять ее перед запуском, не вызывая ее явным образом внутри теста. Есть ли способ сделать это?

Чтобы дать некоторый контекст, возьмите этот тест в качестве примера. Как переместить часть настройки во внешнюю функцию, не вызывая ее в каждом тесте?

func TestBootstrap_LoadError(t *testing.T) {
    // Setup
    mockedLoader := new(MockLoader)
    env.SetLoader(mockedLoader)

    // Given
    mockedLoader.On("Load", mock.Anything).Return(errors.New("error loading .env file"))
    envService := env.EnvService()

    // Test
    err := envService.Bootstrap()

    // Assertions
    assert.Error(t, err)
    assert.False(t, envService.IsBootstrapped())
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
228
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обычно я делаю что-то вроде этого:

func TestSuite(t *testing.T) {
    var mockedLoader *Loader
    
    run := func(name string, fn func()) {
        mockedLoader := new(MockLoader)
        env.SetLoader(mockedLoader)
        t.Run(name, fn())
    }

    run("Test Bootstrap Load Error", func() {
        mockedLoader.On("Load", mock.Anything).Return(errors.New("error loading .env file"))
        envService := env.EnvService()

        // Test
        err := envService.Bootstrap()
        assert.Error(t, err)
        assert.False(t, envService.IsBootstrapped())
    })
}

Где все, что имеет один и тот же код установки, будет в одном тесте «набора», и я, по сути, перехватываю t.Run, чтобы запустить код установки для себя.

Ответ принят как подходящий

Глобальная настройка

В пакете стандартной библиотеки testing есть специальная TestMain функция, которая может быть объявлена ​​один раз для каждого (тестового) пакета и запускаться один раз для всех тестов. Он имеет функцию для запуска тестов и может использоваться для размещения кода настройки и демонтажа для всех тестов в пакете.

func TestMain(m *testing.M) {
    setup()

    // runs all tests in the package
    exitCode := m.Run()

    teardown()

    os.Exit(exitCode)
}

Одним из недостатков TestMain является то, что вам необходимо передавать переменные настройки (например, фиктивное или реальное соединение с БД) в тесты через глобальные тестовые переменные. Невозможно передать их непосредственно в тесты.

Испытательная установка

Если вы хотите использовать стандартную библиотеку, имеющую функцию, которую можно вызывать в каждом тесте для настройки и одну для демонтажа, это вариант, если вам нужна настройка и демонтаж для каждого теста. Здесь переменные можно легко передавать в функции настройки/демонтажа и из них.

func TestExample(t *testing.T) {
    setup()
    defer teardown()

    // test code
}

Другие библиотеки

Существуют и другие библиотеки модульных тестов, которые имеют больше возможностей по настройке и демонтажу. Например, пакет suite пакета testify способен группировать тесты в пакет и выполнять настройку и демонтаж каждого пакета. Несколько пакетов можно объединить в один (тестовый) пакет, что обеспечивает более детальную настройку и контроль демонтажа. Кроме того, он также добавляет больше опций, помимо одной функции настройки и одной функции демонтажа для всего пакета. См. документы.

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


Обычно я придерживаюсь того, что описал в разделе Test Setup. Этого плюс использование подтестов обычно достаточно для контроля над настройкой и демонтажем. См. также этот ответ, чтобы узнать об умном способе управления настройкой и демонтажем для каждого подтеста.

В итоге я использовал github.com/stretchr/testify . Я также видел Ginkgo ( github.com/onsi/ginkgo), который поставляется с этим стилем BDD, но с ним есть некоторые проблемы. Это правда?

Andrea Costanzo 27.02.2024 11:17

Никогда не использовал ginkgo сам

TehSphinX 12.03.2024 13:55

Другие вопросы по теме