0

I have a Go 1.14 project with the following directory structure:

myapp/
  server/
    payments/
      capture_payment.go
      capture_payment_test.go
  billing/
    billing.go
    billing_test.go
  fulfillment/
    fulfillment.go
    fulfillment_test.go

In my billing.go file I have:

package billing

import (
    "fmt"
)

func Flim() {
    fmt.Println("FLIM")
}

In my fulfillment_test.go file I have:

package fulfillment

import (
    "fmt"
)

func Flam() {
    fmt.Println("FLAM")
}

In my capture_payment_test.go file I have:

package payments

import (
  "testing"
  
  "github.com/myorg/myapp/billing"
  "github.com/myorg/myapp/fulfillment"
)

func TestSomething(t *testing.T) {
  billing.Flim()
  fulfillment.Flam()
}

When I cd into server/payments and run go test I get the following error:

$ go test
# github.com/myorg/myapp/server/payments [github.com/myorg/myapp/server/payment.test]
./capture_payment_test.go:12:2: undefined: fulfillment.Flam
FAIL    github.com/myorg/myapp/server/payments [build failed]

Can anyone spot why fulfillment.Flam() is undefined, but billing.Flim() is perfectly fine?

hotmeatballsoup
  • 385
  • 6
  • 58
  • 136
  • 2
    Because test files are not included in the build. If you need testing helper functions that can be imported by other packages you need to declare them in non `_test.go` files. – mkopriva Jun 26 '20 at 08:17
  • Thanks @mkopriva, you're correct: `Flam()` is a testing helper function leveraged from inside `capture_payments_test.go`. So maybe move the entire `fulfillment_test.go` file to be located under the `server/` directory, and change its `package` from "fulfillment" to "payments"? – hotmeatballsoup Jun 26 '20 at 08:23
  • If it is only used by tests of the payments package then that function should probably be declared in that package (note that moving it to server/ and changing the package name to payments does is not the same, that would be a separate "payments" package). If the test helper is intended to be re-used by multiple other packages then it is best to declare it in the package in which it "belongs" (i.e. if it is doing fulfillment related stuff then it belongs to the fulfillment package). – mkopriva Jun 26 '20 at 08:42
  • There is also the pattern of creating packages specifically for providing testing helpers, for example: https://golang.org/pkg/net/http/httptest/, https://golang.org/pkg/testing/iotest/, https://godoc.org/golang.org/x/tools/go/analysis/analysistest. – mkopriva Jun 26 '20 at 08:44

1 Answers1

4

This is explained in the overview of the testing package:

To write a new test suite, create a file whose name ends _test.go .... Put the file in the same package as the one being tested. The file will be excluded from regular package builds ...

This means that Flam() will not be part of the fulfillment package and cannot be used from other packages. If you want test utilities to be used by other packages, you need to put them in regular *.go files rather than *_test.go.

Marc
  • 19,394
  • 6
  • 47
  • 51
  • Ahh thanks @Marc (+1), so `Flam()` is a testing helper function leveraged from inside `capture_payments_test.go`. So maybe move the entire `fulfillment_test.go` to be located under the `server/` directory, and change its `package` from "fulfillment" to "payments"? – hotmeatballsoup Jun 26 '20 at 08:22