Skip to content
keployPublic

Latest commit

 

History

135 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Keploy Go Coverage Agent

This package enables native Go coverage reporting for tests generated by Keploy enterprise. It works by listening for commands from the Keploy binary to start and stop coverage collection for each test case.

How to Use

To integrate the coverage agent into your Go application, follow these two steps:

1. Activate the Agent

Add a blank import for the package in your application's main entry point (e.g., in your main.go file). This import's side effects will automatically initialize and run the coverage agent in the background.

import (
	// ... other imports
	_ "github.com/keploy/go-sdk/v3/keploy"
)

2. Build with Coverage Flags

Compile your application using the -cover and -covermode=atomic flags. These are required for the agent to access and clear coverage data for each test run according to https://pkg.go.dev/runtime/coverage@go1.25rc2#ClearCounters

go build -cover -covermode=atomic -o your-app .

3. Run tests with Keploy enterprise version

sudo -E keploy-enterprise test -c "./your-app" --dedup

Now you will see dedupData.yaml getting created.

Run sudo -E keploy-enterprise dedup to get the tests which are duplicate in duplicates.yaml file

In order to remove the duplicate tests, run the following command:

sudo -E keploy-enterprise dedup --rm

keploytest: Go tests under keploy's Universal Mocker

Package github.com/keploy/go-sdk/v3/keploytest joins a go test suite to keploy mock: keploy records the dependency calls each test makes, replays them in CI, skips the tests listed in keploy/<set>/verdicts.yaml with their reason, and fails a test whose dependency calls changed.

Every top-level test starts with one line:

import "github.com/keploy/go-sdk/v3/keploytest"

func TestPlaceOrder(t *testing.T) {
	defer keploytest.T(t)()
	// ...
}

// A test that goes parallel starts with TP and calls keploytest.Parallel;
// subtests are started with keploytest.Run.
func TestExport(t *testing.T) {
	defer keploytest.TP(t)()
	keploytest.Parallel(t)
	keploytest.Run(t, "csv", func(t *testing.T) { /* ... */ })
}

A value the test makes itself and hands the application, which sends it on to a dependency (a nonce from the test's own clock, a name it made up), differs on every run. Wrap it in keploytest.Given, inside the test, so keploy follows it into the calls that carry it whole and each replay checks that the application sends on the new value:

name := keploytest.Given(t, "app", fmt.Sprintf("[E2E] app-%d", time.Now().UnixNano()))

A replay call that carries another value than the test gave fails the test. For an HTTP call, keploy's run summary names the given (given:app), never a value, and says why: the call carried another value, or a value of another JSON type, at the part of the call it names (body, a header, a path segment), or the test did not give the value before the call.

Give a distinctive value (a UnixNano nonce, a prefixed name), and give the value the application sends on whole: keploy finds a given by its exact text, at any length, and refuses a call value that holds it inside a longer one and changed with it, naming the given (so a short given that stands in another value by chance can be refused too). keploy cannot tell a bare Unix time in seconds or milliseconds, or an RFC 3339 time at the second, from the application's own clock read of that moment. A value the application makes from a given without keeping its text (a hash, a cut, a reformat) is not followed.

keploy follows a given fully into HTTP calls only, and not yet into MongoDB or PostgreSQL calls: a MongoDB field that holds a given whole is followed, and a PostgreSQL statement value that is a given is refused, naming it. A given inside a longer value in a MongoDB or PostgreSQL call is not followed yet, and a MongoDB call's miss of a given does not name it yet.

keploy takes at most 1024 values from one test, each 1 byte to 64 KiB, and at most 64 MiB of givens in one record (names, values and where the tests gave them). Keploy Cloud also holds one test's givens to 1 MiB in all, counted the same way, in a publish to a Keploy branch only, whose tests are served with every snapshot of their set: past it, that publish is refused, naming the test. A keploy.lock recording is held only to keploy's bounds.

Run the suite inside a keploy run, with -p 1 and -v or -json (so a skip and its reason are visible). Set the command once in keploy.yml as mock.command, record with keploy mock record, and replay in CI with:

keploy mock replay -c "go test -p 1 -json ./..."

Run keploy with KEPLOY_PROVEN=1 in its environment (export KEPLOY_PROVEN=1). Without it keploy's agent answers the routes keploytest needs, the claim of the run and Given's among them, with a plain 404, which fails the test with keploytest.ErrNotProven.

Without keploy (KEPLOY_MOCK_AGENT unset or off) the line does nothing and Run/Parallel are t.Run/t.Parallel. With keploy, each test binary claims keploy's run before its tests start, and one test runs at a time: parallel tests run in source order, each with its subtests and cleanups. Parallel test workers (several test binaries at once) arrive in a later keploy release; until then go test runs with -p 1, and the package refuses anything else.