在Go语言的单元测试中,是否可以动态断言两个值是否相等或不相等?

huangapple go评论109阅读模式
英文:

Is it possible to dynamically assert if two values are equal or not equal when unit testing in 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.comparisonResultactualResult相等,第一个测试应该通过;如果两者不相等,第二个测试应该通过。

我查看了testify/assert文档,我不认为找到了类似于我上面编写的EqualOrNotEqual函数的函数,但也许我不小心跳过了某些内容,或者有一些Go特殊语法,我不知道是否可以帮助我实现这个功能。

注意:我很清楚我可以自己编写这个函数。我之所以问是因为如果这是一个成熟的模式,那么包/库通常会将其作为内置函数包含在内,有时可能没有记录/埋在文档中。如果没有,也许有一些原因我不应该这样做,或者也许有更好的方法。开始使用一种新语言一开始非常费力,尤其是因为你必须学习所有新的习惯用法、怪癖和正确的做事方式。

英文:

I've just started using Go. I'm writing unit tests and I'd like to be able to test using a table, where the result to be compared to the actual result sometimes should or should not be equal.

For example, this is the code that I currently have:

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)
		}
	}
}

Now, this isn't too bad, but it would be even better if the last bit could be changed to something cleaner like this for better readability:

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

So, the first test should pass if table.comparisonResult and actualResult are equal, and the second test should pass if the two aren't equal.

I've looked through the testify/assert docs and I don't think I found a function that is similar to the fake EqualOrNotEqual function that I made up above, but perhaps I accidentally skipped over something, or there is some kind of Go special syntax that I don't know about that might help me achieve this.

Note: I am well aware that I can write my own function for this. My reason for asking was because if this is a well-established pattern, then packages/libraries often include it as a built-in function which may at times be undocumented/buried in the documentation. And if not, maybe there's a reason why I shouldn't do this, or maybe there's a better way of doing it. Starting to use a new language is very labour-intensive at first, not least because you have to learn all the new idioms and quirks and The Right Way to do things.

答案1

得分: 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)
}
英文:

Since it's just for readability, and since it appears that this function does not exist, you could just copy-paste your working code into a separate function:

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

and:

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

答案2

得分: 0

Golang确实有一定的函数式编程特性,尽管相对于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)
    }
}
英文:

Golang does have a functional aspect, although it's more rigid than in Python or JavaScript.

You can allow your struct table to hold functions if you know their signatures. Then you get rid of the if logic inside the tests:

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)
	}
}

huangapple
  • 本文由 发表于 2017年5月10日 23:54:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/43897446.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定