Каков наилучший способ синхронизации тестов в разных пакетах, которые связаны с глобальной переменной?

Я работаю над проектом go, моя задача - написать несколько тестов для пакета. Тесты должны получить доступ к глобальной переменной в другом пакете. Эта глобальная переменная может быть setup/access в тестировании разных пакетов. Потому что по умолчанию идет тестирование параллельно для разных пакетов. Поэтому настройка / доступ к этой переменной может создать условия гонки.

Самый простой способ синхронизации - это создать общий sync.Mutex, который охватывает разные пакеты. Сказав это, я попытался поместить этот sync.Mutex в xxx_test.go файла xxx.go, в котором объявлена ​​глобальная переменная, к сожалению, другой пакет не смог получить доступ к этому Mutex из-за ограничения области действия. В конце концов, я понял, что должен поместить этот sync.Mutex в пакет утилит, предназначенный для тестирования, после чего разные пакеты могут получить доступ к этому Mutex для достижения цели синхронизации для этой глобальной переменной.

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

Большое спасибо!

1 ответ

Этот вопрос невероятно широк. На эту тему написаны целые книги.

Но поскольку вы спрашивали конкретно о глобальных переменных, самый простой ответ: не используйте глобальные переменные.

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

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

В качестве упрощенного примера предположим, что у вас есть следующая глобальная переменная и функция, которая ее использует:

var globalFoo = 123

func doFoo() string {
    return fmt.Sprintf("foo = %d", globalFoo)
}

Измените вашу функцию так, чтобы она принимала переменную в качестве аргумента:

func doFoo(foo int) string {
    return fmt.Sprintf("foo = %d", foo)
}

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

В устаревшей кодовой базе одним из методов, позволяющих проводить тестирование без изменения сигнатур функций, является создание простых функций переноса:

func doFoo() string {
    return realDoFoo(globalFoo)
}

func realDoFoo(foo int) string {
    fmt.Sprintf("foo = %s", foo)
}
Другие вопросы по тегам