Go code is organized into packages. Within a package, code can refer to any identifier (name) defined within, while clients of the package may only reference the package's exported types, functions, constants, and variables. Such references always include the package name as a prefix: foo.
The Golang source code itself has a naming convention. If we zero in on an example, like the test where the strings. Compare function is tested, we can see the convention in action: The base test function follows the format of Test + the name of the function under test.
No plurals In go, package names are not plural.
The fundamental difference between the three strategies you've listed is whether or not the test code is in the same package as the code under test. The decision to use package myfunc
or package myfunc_test
in the test file depends on whether you want to perform white-box or black-box testing.
There's nothing wrong with using both methods in a project. For instance, you could have myfunc_whitebox_test.go
and myfunx_blackbox_test.go
.
package myfunc_test
, which will ensure you're only using the exported identifiers.package myfunc
so that you have access to the non-exported identifiers. Good for unit tests that require access to non-exported variables, functions, and methods.myfunc_test.go
uses package myfunc
— In this case the test code in myfunc_test.go
will be in the same package as the code being tested in myfunc.go
, which is myfunc
in this example.myfunc_test.go
uses package myfunc_test
— In this case the test code in myfunc_test.go
"will be compiled as a separate package, and then linked and run with the main test binary." [Source: Lines 58–59 in the test.go source code]myfunc_test.go
uses package myfunc_test
but imports myfunc
using the dot notation — This is a variant of Strategy 2, but uses the dot notation to import myfunc
.It depends on the scope of your tests. High level tests (integration, acceptance, etc...) should probably be placed in a separate package to ensure that you are using the package via the exported API.
If you have a large package with a lot of internals that need to be put under test then use the same package for your tests. But that's not an invitation for your tests to access any bit of private state. That would make refactoring a nightmare. When I write structs in go I am often implementing interfaces. It is those interface methods that I invoke from my tests, not all of the helper methods/functions individually.
You should use strategy 1 whenever possible. You can use the special foo_test
package name to avoid import cycles, but that's mostly there so the standard library can be tested with the same mechanism. For example, strings
cannot be tested with strategy 1 since the testing
package depends on strings
. As you said, with strategy 2 or 3 you don't have access to the package's private identifiers, so it's usually better to not use it unless you have to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With