loading...

re: Java vs Go: Impressive solutions for invented problems VIEW POST

FULL DISCUSSION
 

Hello, great post! I was just wondering how can you share the parameters in go with multiple tests. In junit the parameters can be shared with any test. This way you can test multiple aspects with the same data. The idea is to separate the data from the test. The go example is not exactly the same.

The data is in the test and even Case is defined in the test. Im not saying junit is better in any way, i'm just wondering if there is a way to separate the data from the test so it can be shared.

 

Hi John and thank you for the kind words.

In junit the parameters can be shared with any test. This way you can test multiple aspects with the same data.

Right !
To achieve the same using the host language's constructs, you could:

1. define a package-level variable with the various cases:

type loginCase struct {
    Username string
    Password string
    Expected bool
}

var (
    staticLoginCases = []loginCase{
        {"username", "p@$$w0rd", true},
        {"incorrect-username", "p@$$w0rd", false},
        {"username", "incorrect-p@$$w0rd", false},
    }
)

func TestLogin(t *testing.T) {
    for _, tt := range staticLoginCases {
        t.Run(fmt.Sprintf("login(%s, %s) => %v", tt.Username, tt.Password, tt.Expected), func(t *testing.T) {
            require.Equal(t, tt.Expected, login(tt.Username, tt.Password))
        })
    }
}

func TestAnotherLoginFeature(t *testing.T) {
    for _, tt := range staticLoginCases {
        t.Run(fmt.Sprintf("another test(%s, %s) => %v", tt.Username, tt.Password, tt.Expected), func(t *testing.T) {
            require.Equal(t, tt.Expected, login(tt.Username, tt.Password))
        })
    }
}

2. generate the test cases from a function

type loginCase struct {
    Username string
    Password string
    Expected bool
}

func generateLoginCases() []loginCase {
    var res []loginCase

    res = append(res, loginCase{"username", "p@$$w0rd", true})

    for i := 0; i < 500; i++ {
        res = append(res, loginCase{fmt.Sprintf("user#%d", i), "p@$$w0rd", false})
    }

    return res
}

func TestLogin(t *testing.T) {
    for _, tt := range generateLoginCases() {
        t.Run(fmt.Sprintf("login(%s, %s) => %v", tt.Username, tt.Password, tt.Expected), func(t *testing.T) {
            require.Equal(t, tt.Expected, login(tt.Username, tt.Password))
        })
    }
}

func TestAnotherLoginFeature(t *testing.T) {
    for _, tt := range generateLoginCases() {
        t.Run(fmt.Sprintf("another test(%s, %s) => %v", tt.Username, tt.Password, tt.Expected), func(t *testing.T) {
            require.Equal(t, tt.Expected, login(tt.Username, tt.Password))
        })
    }
}

3. load the test cases from a JSON/Yaml/CSV/.. file

Again, you have the full standard library to achieve whatever you need :)

 

Yes! I think the same style could also be done in junit but it probably wouldn't pass a review. I do think that junit provides some nice ways to remove verbose code and just declare the parameters you want in the test. In some cases it is probably just better not to use it though. It depends on how common the code is and how much time is saves.

In graphs I was able to take advantage of these features in junit here, for example, but it is not for everyone.

code of conduct - report abuse