Каков наилучший способ синхронизации тестов в разных пакетах, которые связаны с глобальной переменной?
Я работаю над проектом 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)
}