go test -exec
xprog -- a test runner for Generic usage with go test
:
$ go test -exec="xprog <command> [opts] --" <go-packages> [go-test-flags]
Cross-compile the tests and run them on the target, connect via SSH:
$ GOOS=linux go test -exec="xprog ssh [opts] --" <go-packages> [go-test-flags]
As above, but collect also code coverage and show it on the host:
$ GOOS=linux go test -coverprofile=coverage.out -exec="xprog ssh [opts] --" <go-packages> [go-test-flags] &&
go tool cover -html=coverage.out
To see xprog
output, pass -v
both to xprog
and go test
:
$ go test -v -exec="xprog -v <command> [opts] --" <go-packages> [go-test-flags]
Install
$ go install github.com/marco-m/xprog/cmd/xprog@latest
Writing tests that will not harm YOUR host
If you have at least one test that exercises a destructive or invasive function, it is of the utmost importance to ensure that running go test
in the default Go way:
$ go test ./...
(maybe you forgot about xprog, or somebody new to the project) will not cause harm to the host system!
Consider functions Harmless
and Destructive
(examples/example.go):
package examples
func Harmless() {
fmt.Fprintln(os.Stderr, "hello from Harmless on", runtime.GOOS)
}
// For example: delete and add files, invoke programs, ...
func Destructive() {
fmt.Fprintln(os.Stderr, "hello from Destructive on", runtime.GOOS)
}
We can test Harmless
as usual (examples/example_test.go):
func TestHarmless(t *testing.T) {
examples.Harmless()
}
On the other hand, we want to be sure that Destructive
is tested ONLY on the VM target. This can be achieved as follows (examples/example_test.go):
import "github.com/marco-m/xprog"
func TestDestructiveXprog(t *testing.T) {
if xprog.Absent() {
t.Skip("skip: test requires xprog")
}
examples.Destructive()
}
Running the tests on the host as usual, note that TestDestructiveXprog
is skipped:
$ go test -v ./examples
=== RUN TestHarmless
hello from Harmless on darwin
--- PASS: TestHarmless (0.00s)
=== RUN TestDestructiveXprog
example_test.go:21: skip: test requires xprog
--- SKIP: TestDestructiveXprog (0.00s)
PASS
ok github.com/marco-m/xprog/examples
Running the tests on the target VM via xprog
, note that TestDestructiveXprog
runs:
$ GOOS=linux go test -v -exec="xprog ssh -cfg $PWD/ssh_config --" ./examples
=== RUN TestHarmless
hello from Harmless on linux
--- PASS: TestHarmless (0.00s)
=== RUN TestDestructiveXprog
hello from Destructive on linux
--- PASS: TestDestructiveXprog (0.00s)
PASS
ok github.com/marco-m/xprog/examples
Running tests as root
To do this, be sure that the tests are safe to run everywhere (see section above).
Then, add --sudo
to the ssh
command.
This assumes a passwordless sudo on the target (what you get by default on a Vagrant VM).
Usage
For details, have a look at the targets in the Taskfile, they are commented.
Quick preparation
$ virtualbox up
;; Generate a SSH configuration file
$ vagrant ssh-config > ssh_config
Quick usage
Cross-compile the tests and run them on the target, using xprog ssh
:
$ GOOS=linux go test -exec="xprog ssh --cfg $PWD/ssh_config --" ./... -v
Stop the VM when done
vagrant halt
More controlled preparation
See task prepare-vm
or
$ vagrant destroy --force
$ vagrant up
;; Take snapshot, name `pristine`
$ vagrant snapshot save pristine
;; Generate a SSH configuration file
$ vagrant ssh-config > ssh_config
More controlled usage
See task test:vm:...
Run the VM-based tests on the VM current filesystem (faster but inaccurate):
$ GOOS=linux go test -coverprofile=coverage.out -exec="$PWD/bin/xprog ssh --cfg $PWD/ssh_config --" ./... -v
Or: run the VM-based tests from a clean snapshot:
$ vagrant snapshot restore pristine
$ GOOS=linux go test -coverprofile=coverage.out -exec="$PWD/bin/xprog ssh --cfg $PWD/ssh_config --" ./... -v
Notes
go test
will execute xprog
in the directory (or directories) corresponding to the package(s) specified to the go test
invocation. For example:
$ go test -exec="xprog ssh --cfg $PWD/ssh_config --" ./foo
will run xprog
in directory ./foo
. This is why it is important to specify the ssh_config file with an absolute path: --cfg $PWD/ssh_config
, so that it will be found no matter the xprog
working directory.
Limitations
Configuration
xprog ssh
expects a ssh_config
file generated by vagrant ssh-config
and will pick the first Host
entry.
Reserved environment variables
The prefix XPROG_SYS_
is reserved for xprog internal usage. Messing with it can cause xprog.Absent()
to return false positives and thus destructive tests will run also on your host.
License
See LICENSE.