Какова процедура проверки времени во время проведения тестов?

Я пишу тесты для слоя repository с использованием реальной базы данных (<a href="https://testcontainers.com/" rel="nofollow">https://testcontainers.com/</a>) и столкнулся с проблемой при проверке структур, содержащих тип time.Time. 

В качестве примера, вот результат одного из моих тестов: 

Тест завершается с ошибкой: 
<pre><code>Error:          Not equal:
                                        expected: &amp;model.ColorSQL{ID:1, Name:"Cullen Gerhold", CreatedAt:time.Date(2025, time.March, 15, 20, 50, 54, 823874100, time.UTC), UpdatedAt:time.Date(2025, time.March, 15, 20, 50, 54, 823874100, time.UTC), DeletedAt:&lt;nil&gt;}
                                        actual  : &amp;model.ColorSQL{ID:1, Name:"Cullen Gerhold", CreatedAt:time.Date(2025, time.March, 15, 20, 50, 54, 822076000, time.UTC), UpdatedAt:time.Date(2025, time.March, 15, 20, 50, 54, 822076000, time.UTC), DeletedAt:&lt;nil&gt;}</code></pre> 

Первая мысль была в том, чтобы обновить код следующим образом: 

Однако, если я решу обновить структуру и добавлю в нее новые поля, существует риск, что я забуду обновить соответствующие тесты. В результате, тесты могут пройти успешно, даже если новые поля не будут проверяться. Как можно избежать этой проблемы?
  • 15 марта 2025 г. 21:04
Ответы на вопрос 2
Проблемы с проверкой значений типа `time.Time` в тестах достаточно распространены, особенно когда дело касается точности времени, так как даже небольшие изменения могут привести к неравенству. Ваша ситуация показывает, что есть разница в наносекундах между ожидаемым и актуальным значением времени.

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

### 1. Используйте сравнение без учета наносекунд

Если для вашего случая важна только точность до секунд и потенциальные различия в наносекундах можно игнорировать, вы можете сравнивать `time.Time` значения, убирая наносекунды:

```go
func equalTimes(t1, t2 time.Time) bool {
    return t1.Unix() == t2.Unix() && t1.Location() == t2.Location()
}
```

Затем в вашем тесте используйте эту функцию вместо прямого сравнения.

### 2. Определите структурированные методы сравнения

Если вам требуется более сложная логика для сравнения ваших структур, вы можете определить метод для сравнения полей:

```go
type ColorSQL struct {
    ID        int
    Name      string
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt *time.Time
}

func (c *ColorSQL) Equal(other *ColorSQL) bool {
    return c.ID == other.ID &&
        c.Name == other.Name &&
        equalTimes(c.CreatedAt, other.CreatedAt) &&
        equalTimes(c.UpdatedAt, other.UpdatedAt) &&
        // Сравнение DeletedAt требует дополнительной логики
        (c.DeletedAt == nil && other.DeletedAt == nil ||
         (c.DeletedAt != nil && other.DeletedAt != nil && c.DeletedAt.Equal(*other.DeletedAt)))
}
```

Теперь вы можете использовать `c.Equal(&actualColor)` для проверки на равенство.

### 3. Стать педантичным в тестах

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

```go
if !expected.Equal(&actual) {
    t.Errorf("Expected %v but got %v", expected, actual)
}
```

### 4. Mocking времени

Иногда полезно использовать библиотеку, которая позволяет "замокировать" текущее время. Одна из таких библиотек - `github.com/jonboulle/clockwork`, которая предоставляет интерфейс для работы с временем. Это может помочь вам избежать вероятностей, связанных с реальным временем.

### 5. Значения по умолчанию

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

### Заключение

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