marco-m / xprog

xprog -- a test runner for go test -exec

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

xprog -- a test runner for go test -exec

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.

Credits

About

xprog -- a test runner for go test -exec

License:MIT License


Languages

Language:Go 100.0%