gotests

package
v0.0.0-...-f078915 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 5, 2024 License: BSD-3-Clause Imports: 14 Imported by: 4

README

gotests

import "github.com/blueprint-uservices/blueprint/plugins/gotests"

Package gotests provides a Blueprint plugin for automatically converting black-box workflow spec unit tests into tests that can run against a compiled Blueprint system.

If you have developed a Blueprint application, then you have probably also written tests of your workflow services. The gotests plugin lets you leverage those tests and automatically convert them into tests that can run against the compiled applciation.

In addition to the documentation here, the Workflow Tests page of the user manual has more information.

Wiring Spec Usage

To use the gotests plugin in a wiring spec, specify which services you want to test:

gotests.Test(spec, "my_service")

The gotests plugin will search for any compatible black-box tests, then convert those tests into tests that use clients to the compiled Blueprint application.

Blueprint tests are typically written in a standalone module, and thus the tests module will need to be explicitly added to the wiring's go.mod. The most straightforward way to do this is, somewhere in the wiring spec (e.g. in main.go) add an anonymous import statement then manually add the workflow spec search path:

import _ "github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests"

workflowspec.AddModule("github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests")
Running Tests

After compiling your application, navigate to `gotests` in the output directory. Within this workspace will be a copy of your test module; let's assume it is called `tests`.

Before running the compiled tests, make sure you have started the compiled application. Then:

cd gotests/tests
go test .

You can use the usual gotest command line arguments to specify individual tests to run.

Depending on the configuration you compiled, the tests might fail due to missing environment variables / arguments. For example, the tests will probably need to know the addresses of services to contact. Remedy this by providing those addresses as command line arguments as appropriate.

Writing Tests: Test Location

The gotests plugin is intended for use with black-box tests of workflow logic. Most Blueprint applications will implement a bunch of services as part of their workflow; ideally developers also write some tests for those services, that make API calls to the service and check the receive results. These are *black-box* tests because they only look at the externally-visible inputs and outputs of the service.

By convention we recommend putting black-box tests in a sibling module to the workflow. See for example the SockShop Tests or Train Ticket Tests, which have separate tests and workflow modules.

When compiling a wiring spec, the gotests plugin will need to find the location of the tests. This is achieved by (1) ensuring that the test module is in your go.mod; and (2) ensuring that the module is added to the workflow spec search path.

The simplest way of ensuring that the test module is in your go.mod is to add an import statement somewhere in your wiring spec, such as in main.go:

import _ "github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests"

Then manually configure the workflowspec search path:

workflowspec.AddModule("github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests")

If the go compiler complains "no non-test Go files in ..." then add a dummy file to the tests module, e.g. doc.go, that declares the package.

Writing Tests: Test Compatibility

For a test to be compatible with the gotests plugin, it must make use of the registry.ServiceRegistry to acquire service instances. The Train Ticket application's User Service demonstrates the use of the ServiceRegistry, which we also explain here:

First, in your test file, declare a service registry as a var:

var userServiceRegistry = registry.NewServiceRegistry[user.UserService]("user_service")

Second, add an init function that instantiates the User Service *locally*. This local instantiation will enable you to run unit tests locally on the workflow spec without having to compile the application

func init() {
    	userServiceRegistry.Register("local", func(ctx context.Context) (user.UserService, error) {
    		db, err := simplenosqldb.NewSimpleNoSQLDB(ctx)
    		if err != nil {
    			return nil, err
	    	}
	    	return user.NewUserServiceImpl(ctx, db)
	    })
    }

Next, you can write a black-box unit test by using the ServiceRegistry's Get method to acquire the userService instance

func TestUserService(t *testing.T) {
	ctx := context.Background()
	service, err := userServiceRegistry.Get(ctx)
	require.NoError(t, err)
 	// ...
}

Your tests are now ready to be used with the gotests plugin. You can also just run the tests locally, using `go test .` from your test module.

To summarize, tests are only compatible with the gotests plugin if they:

  • are contained in a separate module from the workflow spec
  • the test module is on the workflow spec search path
  • the tests declare a registry.ServiceRegistry var
  • the tests using ServiceRegistry.Get to get the service instance to test.
Edge Cases

Your black-box tests should ideally be idempotent (e.g. if you call Create to instantiate something then you should call Delete to remove it too), since we do not automatically spin up / tear down new system instances on your behalf. If you have a large number of services and tests in your application, it is possible that one test might leave behind state in the application that causes a different test to fail. You can remedy this by either making the system idempotent, or manually restarting the system and running tests individually.

Index

func Test

func Test(spec wiring.WiringSpec, servicesToTest ...string) string

Test can be used by wiring specs to convert existing black-box workflow tests into tests that use generated service clients and can be run against the compiled Blueprint application.

After compilation, the output will contain a golang workspace called "gotests" that will include modified versions of the source tests.

servicesToTest should be the names of golang services instantiated in the wiring spec.

The gotests plugin searches for any workflow packages with tests that make use of registry.ServiceRegistry. Matching modules are copied to an output golang workspace caled "tests". Matching packges in the output workspace will have a file blueprint_clients.go that registers a service client.

Returns the name "gotests" which must be included when later calling [wiring.WiringSpec.BuildIR]

For more information about tests see Workflow Tests.

Generated by gomarkdoc

Documentation

Overview

Package gotests provides a Blueprint plugin for automatically converting black-box workflow spec unit tests into tests that can run against a compiled Blueprint system.

If you have developed a Blueprint application, then you have probably also written tests of your workflow services. The gotests plugin lets you leverage those tests and automatically convert them into tests that can run against the compiled applciation.

In addition to the documentation here, the Workflow Tests page of the user manual has more information.

Wiring Spec Usage

To use the gotests plugin in a wiring spec, specify which services you want to test:

gotests.Test(spec, "my_service")

The gotests plugin will search for any compatible black-box tests, then convert those tests into tests that use clients to the compiled Blueprint application.

Blueprint tests are typically written in a standalone module, and thus the tests module will need to be explicitly added to the wiring's go.mod. The most straightforward way to do this is, somewhere in the wiring spec (e.g. in main.go) add an anonymous import statement then manually add the workflow spec search path:

import _ "github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests"

workflowspec.AddModule("github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests")

Running Tests

After compiling your application, navigate to `gotests` in the output directory. Within this workspace will be a copy of your test module; let's assume it is called `tests`.

Before running the compiled tests, make sure you have started the compiled application. Then:

cd gotests/tests
go test .

You can use the usual gotest command line arguments to specify individual tests to run.

Depending on the configuration you compiled, the tests might fail due to missing environment variables / arguments. For example, the tests will probably need to know the addresses of services to contact. Remedy this by providing those addresses as command line arguments as appropriate.

Writing Tests: Test Location

The gotests plugin is intended for use with black-box tests of workflow logic. Most Blueprint applications will implement a bunch of services as part of their workflow; ideally developers also write some tests for those services, that make API calls to the service and check the receive results. These are *black-box* tests because they only look at the externally-visible inputs and outputs of the service.

By convention we recommend putting black-box tests in a sibling module to the workflow. See for example the SockShop Tests or Train Ticket Tests, which have separate tests and workflow modules.

When compiling a wiring spec, the gotests plugin will need to find the location of the tests. This is achieved by (1) ensuring that the test module is in your go.mod; and (2) ensuring that the module is added to the workflow spec search path.

The simplest way of ensuring that the test module is in your go.mod is to add an import statement somewhere in your wiring spec, such as in main.go:

import _ "github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests"

Then manually configure the workflowspec search path:

workflowspec.AddModule("github.com/blueprint-uservices/blueprint/examples/dsb_hotel/tests")

If the go compiler complains "no non-test Go files in ..." then add a dummy file to the tests module, e.g. doc.go, that declares the package.

Writing Tests: Test Compatibility

For a test to be compatible with the gotests plugin, it must make use of the registry.ServiceRegistry to acquire service instances. The Train Ticket application's User Service demonstrates the use of the ServiceRegistry, which we also explain here:

First, in your test file, declare a service registry as a var:

var userServiceRegistry = registry.NewServiceRegistry[user.UserService]("user_service")

Second, add an init function that instantiates the User Service *locally*. This local instantiation will enable you to run unit tests locally on the workflow spec without having to compile the application

    func init() {
    	userServiceRegistry.Register("local", func(ctx context.Context) (user.UserService, error) {
    		db, err := simplenosqldb.NewSimpleNoSQLDB(ctx)
    		if err != nil {
    			return nil, err
	    	}
	    	return user.NewUserServiceImpl(ctx, db)
	    })
    }

Next, you can write a black-box unit test by using the ServiceRegistry's Get method to acquire the userService instance

func TestUserService(t *testing.T) {
	ctx := context.Background()
	service, err := userServiceRegistry.Get(ctx)
	require.NoError(t, err)
 	// ...
}

Your tests are now ready to be used with the gotests plugin. You can also just run the tests locally, using `go test .` from your test module.

To summarize, tests are only compatible with the gotests plugin if they:

  • are contained in a separate module from the workflow spec
  • the test module is on the workflow spec search path
  • the tests declare a registry.ServiceRegistry var
  • the tests using ServiceRegistry.Get to get the service instance to test.

Edge Cases

Your black-box tests should ideally be idempotent (e.g. if you call Create to instantiate something then you should call Delete to remove it too), since we do not automatically spin up / tear down new system instances on your behalf. If you have a large number of services and tests in your application, it is possible that one test might leave behind state in the application that causes a different test to fail. You can remedy this by either making the system idempotent, or manually restarting the system and running tests individually.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Test

func Test(spec wiring.WiringSpec, servicesToTest ...string) string

Test can be used by wiring specs to convert existing black-box workflow tests into tests that use generated service clients and can be run against the compiled Blueprint application.

After compilation, the output will contain a golang workspace called "gotests" that will include modified versions of the source tests.

servicesToTest should be the names of golang services instantiated in the wiring spec.

The gotests plugin searches for any workflow packages with tests that make use of registry.ServiceRegistry. Matching modules are copied to an output golang workspace caled "tests". Matching packges in the output workspace will have a file blueprint_clients.go that registers a service client.

Returns the name "gotests" which must be included when later calling wiring.WiringSpec.BuildIR

For more information about tests see Workflow Tests.

Types

This section is empty.

Directories

Path Synopsis
Package codegen implements the gotest plugin's code generation logic.
Package codegen implements the gotest plugin's code generation logic.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL