Service - Integration Test Config: Difference between revisions
Line 114: | Line 114: | ||
<syntaxhighlight lang="JavaScript" inline>{propertyName}</syntaxhighlight>: name of a property in the input/output. | <syntaxhighlight lang="JavaScript" inline>{propertyName}</syntaxhighlight>: name of a property in the input/output. | ||
<syntaxhighlight lang="JavaScript" inline>testValueMatches: false</syntaxhighlight> can be used in local unit tests to generate complete AWS mock responses for outputEvents including properties that are needed but do not need to be tested. | |||
<syntaxhighlight lang="JavaScript" inline>forStageMatching</syntaxhighlight> can be used in local unit tests when creating AWSMock, will skip properties that set this to false when matching a Lambda invocation being mocked. | |||
<syntaxhighlight lang="JavaScript" inline>testValueMatches</syntaxhighlight> and <syntaxhighlight lang="JavaScript" inline>forStageMatching</syntaxhighlight> can be used for testing inputEvents, for example when a Lambda is invoked you can set a property to <syntaxhighlight lang="JavaScript" inline>testValueMatches: true</syntaxhighlight> and <syntaxhighlight lang="JavaScript" inline>forStageMatching: false</syntaxhighlight>, forStageMatching set to false means this property will not be used to find a matching stage to test, testValueMatches will mean the value of the property will be tested to see if it matches, and cause the stage's test to fail if it does not match. | <syntaxhighlight lang="JavaScript" inline>testValueMatches</syntaxhighlight> and <syntaxhighlight lang="JavaScript" inline>forStageMatching</syntaxhighlight> can be used for testing inputEvents, for example when a Lambda is invoked you can set a property to <syntaxhighlight lang="JavaScript" inline>testValueMatches: true</syntaxhighlight> and <syntaxhighlight lang="JavaScript" inline>forStageMatching: false</syntaxhighlight>, forStageMatching set to false means this property will not be used to find a matching stage to test, testValueMatches will mean the value of the property will be tested to see if it matches, and cause the stage's test to fail if it does not match. | ||
== Local unit tests - Lambda requests == | == Local unit tests - Lambda requests == |
Revision as of 09:17, 8 September 2020
Overview
This service is intended to be used both for offline local unit testing individual services, and for multi-step/multi-service deployed integration tests.
Using this service we can configure integration tests and use that same configuration to build mocked unit tests in a local environment, pulling out only the steps that apply to a single service.
The main purpose of this service is to configure integration tests for the current project that will then be used by either the local test environment or deployed by the Integration Testing service
The reasoning behind splitting integration test configuration into a separate service, rather than incorporated into each individual service, is to keep the main services lean and remove code duplication. Tests that pass from one service to another will have shared details, the expected output from one will be the expected input the other.
Repository structure
The configuration files separate different elements of the test to allow for re-use, as follows:
The repositories root directory has a sub-directory named test_config that holds user-configurable setup files, it has services, events and tests sub-directories:
test_config/services
Holds service specific configurations, the services directory is separated into one sub-directory per service, the directory name matches each deployed service's iz_serviceName.
Each per services directory has a resources.js file:
test_config/services/{ServiceName}/resources.js
Resources that are tested at one point during an integration test flow, for example one Lambda function.
test_config/events
Expected input/output objects, can be used to start tests or as message objects sent between resources that can tests can be performed on. Any number of .js files can be added to this directory.
test_config/tests
Configures the tests, any number of .js files can be added to this directory.
Lambda Functions
getIntegrationTests
/**
* Returns an array of integration test configs
* @param {string} [integrationTestTag] - Only return test with matching integrationTestTag
* @param {string} [serviceName] - Only return tests where initialStage serviceName matches
* @param {string} [resourceType] - Only return tests where initialStage resourceType matches
* @param {string} [resourceName] - Only return tests where initialStage resourceName matches
*
* @returns {object} One resource configuration
*/
module.exports.getIntegrationTests = (serviceName, resourceType, resourceName) => {
integrationTestTag / serviceName / resourceType / resourceName parameters are optional, if excluded then all tests will be returned. If integrationTestTag is defined then serviceName / resourceType / resourceName are ignored.
getEventConfig
/**
* Get the configuration for one event
* @param {string} eventTag - Tag of the event required
*
* @returns {object} One event configuration
*/
module.exports.getEventConfig = (serviceName, resourceType, resourceName) => {
resources.js Syntax
Has one module.exports function that returns an an object of all available resources, the structure is:
{resourceType}: {
{resourceName}:{
localLocation: ".. location relative to project's root directory" //Lambda only
localHandler: ".. name of the modules handler function" //Lambda only
},
..
},
..
{resourceType}
: groups resources into types, supported types: Lambda, DynamoDB.
{resourceName}
: the full name of the deployed resource, we can standardize these within the function for example by adding a variable at the top of the module that sets the name of each service.
events/*.js Syntax
For each step in an integration test that spans multiple resources there will be expected input and output objects, these are configured separately to the integration tests themselves so local unit test config for each service can extract just the events required, allows integration tests to branch into multiple paths each with tests performed, and offers re-use opportunities.
the events directory can have any number of .js files, each file must export an EventConfig function, which returns an object of any number of event configurations.
Example:
module.exports.EventConfig = () => {
return {
{eventTag}: {
properties:{
{propertyName}:{
value: ".."
testValueMatches: true|false, //default: true, whether value of this property is checked when performing test
forStageMatching: true|false, //default: true, whether this property is used to match stage config during integration tests
//others, eg greater_than, substring etc..
}
},
..
}
},
..
}
};
{eventTag}
: unique tag name for this event.
{propertyName}
: name of a property in the input/output.
testValueMatches: false
can be used in local unit tests to generate complete AWS mock responses for outputEvents including properties that are needed but do not need to be tested.
forStageMatching
can be used in local unit tests when creating AWSMock, will skip properties that set this to false when matching a Lambda invocation being mocked.
testValueMatches
and forStageMatching
can be used for testing inputEvents, for example when a Lambda is invoked you can set a property to testValueMatches: true
and forStageMatching: false
, forStageMatching set to false means this property will not be used to find a matching stage to test, testValueMatches will mean the value of the property will be tested to see if it matches, and cause the stage's test to fail if it does not match.
Local unit tests - Lambda requests
Events that are intended to be lambda requests can be applied by local unit tests in two ways:
- As an initial request event sent into a handler function.
- If the lambda handler being tested invokes another Lambda we can test the sent out request matches the expected event.
Local unit tests - Lambda responses
Events intended to be lambda responses can be applied by local unit tests in two ways:
- As the result of a tested lambda function, we can assert tests to see the function response matches the expected event
- We can use response events to generate AWS Mock responses from other Lambda functions the tested Lambda sends requests to.
tests/*.js Syntax
Configures the integration tests, including the initial entry point and what events to monitor and perform tests on.
The tests directory can have any number of .js files, each file must export a TestConfig function which returns an array of test configurations
Example:
module.exports.TestConfig = () => {
return [
{
integrationTestTag: {integrationTestTag},
testSettings: {
productionSafe: true|false, //default false
errorIfStageUndefined: true|false, //default false
errorIfInvokeUndefined: true|false, //default false
},
stages:[
{
initialStage: true, //if set to true is the starting point for this integration test
eventStageTag: {eventStageTag}, //optional
inputEventTag: {eventTag}, //event that triggers this stage
resource: {
serviceName: {ServiceName},
resourceType: {resourceType},
resourceName: {resourceName},
},
invokes: [ //resources that are invoked from this stage
{
serviceName: {ServiceName},
resourceType: {resourceType},
resourceName: {resourceName},
inputEventTag: {eventTag}, //event that is sent to the invoked resource
outputEventTag: {eventTag} //expected return value from the invoked resource
},
{
eventStageTag: {eventStageTag} //references another stage in this integration test
},
..
],
outputEventTag: {eventTag} //return value from this stage, eg Lambda return value
},
..
]
},
..
]
}
{integrationTestTag}
: unique tag name for this integration test.
{eventStageTag}
: unique tag name for one stage in an integration test, is optional and can be refered to in the integration test's invokes
array
Set tests to not invoke in production environment
Local test environment and Test environment deployed on AWS want to invoke as many tests as possible, including tests that can be invoked in the Production environment deployed on AWS, however the Production environment wants to strictly restrict tests to ones that affect the live project such as by changing state.
This separation of tests could be achieved by having a different configuration of tests for Test environments vs Production, another option that reduces managing test configs in two locations is finding a clear way to differentiate which tests are not done in Production, have done this be defaulting to test environment and requiring production_safe to be added to any test that can be performed in production environment.
This could be achieved by placing the tests in different files (so it is cleared for developers which they are adding), and using the iz_stage environment variable to choose which files to load as available tests.
Generating local unit tests
Use the izara-testing module to run tests generated from this service.