3

I have a file called example.go and another test file called example_test.go and they are both in the same package. I would like to test some unexported functions in example.go

When I run the test, the unexported functions are undefined in example_test.go. I am wondering what is the best convention of testing unexported functions in a test file that are in the same package?

gogofan
  • 533
  • 1
  • 10
  • 20
  • 4
    Please show a [mcve]. If the test file is in the same package, then it has access to all the package level identifiers. – JimB Sep 27 '17 at 14:55
  • 2
    If they are in the same package all functions and global variables should be accessible to each other. How are you running your tests? `go test ./...` ? – reticentroot Sep 27 '17 at 14:56
  • 1
    Unexported identifiers are only accessible from the same package, so use the same package declaration inside `example_test.go` (white-box testing). It also must be in the same folder as `example.go`. For more details see [How can I allow one package access to another package's unexported data only when testing?](https://stackoverflow.com/questions/42930944/how-can-i-allow-one-package-access-to-another-packages-unexported-data-only-whe/42931290#42931290) – icza Sep 27 '17 at 15:05
  • If both files are in directory `foo/bar/`, how should I run the go test function? – gogofan Sep 27 '17 at 15:06
  • 2
    How are you running now? Simply change directory to `foo/bar/`, then run `go test`. – icza Sep 27 '17 at 15:11
  • 2
    "When I run the test, the unexported functions are undefined" No they are not. You are making an other mistake. – Volker Sep 27 '17 at 15:50
  • I managed to test the unexported functions when changing to the directory. The mistake before was I was doing `go test foo/bar/example_test.go` – gogofan Sep 28 '17 at 13:40
  • Ah yes, that's a confusing mistake; when you specify a file Go will compile just that file, instead of the package. In Go, you almost always to to specify packages (i.e. `foo/bar`) and almost never files (this applies to most `go` commands). – Martin Tournoij Sep 29 '17 at 21:05

3 Answers3

8

This will also work for private member functions of a private type.

For example.

abc.go is as follows

package main

type abc struct {
        A string
}

func (a *abc) privateFunc() {

}

abc_test.go is as follows

package main

import "testing"

func TestAbc(t *testing.T) {
        a := new(abc)
        a.privateFunc()
}

Running go test on this should give you a full pass without any errors.

linux-/bin/bash@~/trials/go$ go test -v
=== RUN   TestAbc
--- PASS: TestAbc (0.00s)
PASS
ok      _/home/george/trials/go        0.005s
msanford
  • 11,803
  • 11
  • 66
  • 93
George Thomas
  • 1,246
  • 2
  • 11
  • 14
7

If your files are truly in the same package, this should not be an issue. I am able to run the below test with no problem.

directory structure:

~/Source/src/scratch/JeffreyYong-Example$ tree .
.
├── example.go
└── example_test.go

example.go:

package example

import "fmt"

func unexportedFunc() {
    fmt.Println("this totally is a real function")
}

example_test.go

package example

import "testing"

func TestUnimportedFunc(t *testing.T) {
    //some test conditions
    unexportedFunc()
}

test command:

~/Source/src/scratch/JeffreyYong-Example$ go test -v .

output:

=== RUN   TestUnimportedFunc
this totally is a real function
--- PASS: TestUnimportedFunc (0.00s)
PASS
ok      scratch/JeffreyYong-Example     0.001s
Opnauticus
  • 662
  • 4
  • 9
  • example_test is a different package. but still valid – Eaton Emmerich Jan 04 '20 at 10:24
  • That is incorrect, both files declare they are in the `example` package. If they were in separate packages (lets say `A` and `B`), the test in package B would need to reference the function in package A, which would not be possible, because the function in package A is not exported - as in the original post. – Opnauticus Jan 07 '20 at 19:21
  • ["When importing a package, you can refer only to its exported names. Any "unexported" names are not accessible from outside the package."](https://tour.golang.org/basics/3) – Opnauticus Jan 07 '20 at 19:24
  • Just indicating a common mistake that was not mentioned in answer. saying that example_test and example is not the same package in all ways, means that we can declare a second package in one directory, which is not the case. Something like: "The _test package is not the same package, and unit tests don't have to be in them" would be useful information. – Eaton Emmerich Jan 17 '20 at 15:41
1

Running go test /path/to/testfile_test.go Will not automatically compile any defenitions made in /path/to/testfile.go

You can run the test with go test /path/to/ instead.

Eaton Emmerich
  • 452
  • 4
  • 17