Можно ли динамически утверждать, что два значения равны или не равны при модульном тестировании в Go?

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

Например, это код, который у меня сейчас есть:

package main

import (
    "github.com/stretchr/testify/assert"
    "testing"
)

func TestFunc(t *testing.T) {
    tables := []struct {
        input               string
        comparisonResult    string
        shouldBeEqual       bool
    }{
        {
            "some irrelevant input",
            "some result",
            true,
        },
        {
            "some other irrelevant input",
            "some other result",
            false,
        },
    }

    for _, table := range tables {
        actualResult := sampleFunc(table.input)
        if table.shouldBeEqual {
            assert.Equal(t, table.expectedResult, actualResult)
        } else {
            assert.NotEqual(t, table.expectedResult, actualResult)
        }
    }
}

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

for _, table := range tables {
    actualResult := sampleFunc(table.input)
    assert.EqualOrNotEqual(t, table.comparisonResult, actualResult, table.shouldBeEqual)
}

Итак, первый тест должен пройти, если table.comparisonResult а также actualResult равны, и второй тест должен пройти, если два не равны.

Я посмотрел через testify/assert документы, и я не думаю, что я нашел функцию, которая похожа на подделку EqualOrNotEqual функции, которую я составил выше, но, возможно, я случайно пропустил что-то, или есть какой-то специальный синтаксис Go, о котором я не знаю, который мог бы помочь мне достичь этого.

Примечание: я хорошо знаю, что могу написать свою собственную функцию для этого. Моя причина была в том, что если это хорошо установленный шаблон, то пакеты / библиотеки часто включают его в качестве встроенной функции, которая иногда может быть недокументирована / похоронена в документации. А если нет, возможно, есть причина, почему я не должен этого делать, или, может быть, есть лучший способ сделать это. Начать использовать новый язык поначалу очень трудоемко, не в последнюю очередь потому, что вам нужно выучить все новые идиомы и причуды, а также "Правильный путь".

2 ответа

Так как это просто для удобства чтения, и поскольку кажется, что эта функция не существует, вы можете просто скопировать и вставить свой рабочий код в отдельную функцию:

func equalOrNotEqual(t TestingT, expected, actual interface{}, shouldBeEqual bool) {
    if shouldBeEqual {
        assert.Equal(t, expected, actual)
    } else {
        assert.NotEqual(t, expected, actual)
    }
}

а также:

for _, table := range tables {
    actualResult := sampleFunc(table.input)
    equalOrNotEqual(t, table.comparisonResult, actualResult, table.shouldBeEqual)
}

У Голанга есть функциональный аспект, хотя он более жесткий, чем в Python или JavaScript.

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

func TestFunc(t *testing.T) {
    tables := []struct {
        input            string
        comparisonResult string
        assert           func(assert.TestingT, interface{}, interface{}, ...interface{}) bool
    }{
        {
            input:            "some irrelevant input",
            comparisonResult: "some result",
            assert:           assert.Equal,
        },
        {
            input:            "some other irrelevant input",
            comparisonResult: "some other result",
            assert:           assert.NotEqual,
        },
    }

    for _, table := range tables {
        actualResult := sampleFunc(table.input)
        table.assert(t, table.comparisonResult, actualResult)
    }
}
Другие вопросы по тегам