docs: add module documentation testing (#12762)
This commit is contained in:
@@ -11,28 +11,28 @@ PROPOSED Partially Implemented
|
||||
## Abstract
|
||||
|
||||
Recent work in the SDK aimed at breaking apart the monolithic root go module has highlighted
|
||||
shortcomings and inconsistencies in our testing paradigm. This ADR clarifies a common
|
||||
shortcomings and inconsistencies in our testing paradigm. This ADR clarifies a common
|
||||
language for talking about test scopes and proposes an ideal state of tests at each scope.
|
||||
|
||||
## Context
|
||||
|
||||
[ADR-053: Go Module Refactoring](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-053-go-module-refactoring.md) expresses our desire for an SDK composed of many
|
||||
independently versioned Go modules, and [ADR-057: App Wiring Part I](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-057-app-wiring-1.md) offers a methodology
|
||||
for breaking apart inter-module dependencies through the use of dependency injection. As
|
||||
for breaking apart inter-module dependencies through the use of dependency injection. As
|
||||
described in [EPIC: Separate all SDK modules into standalone go modules](https://github.com/cosmos/cosmos-sdk/issues/11899), module
|
||||
dependencies are particularly complected in the test phase, where simapp is used as
|
||||
the key test fixture in setting up and running tests. It is clear that the successful
|
||||
the key test fixture in setting up and running tests. It is clear that the successful
|
||||
completion of Phases 3 and 4 in that EPIC require the resolution of this dependency problem.
|
||||
|
||||
In [EPIC: Unit Testing of Modules via Mocks](https://github.com/cosmos/cosmos-sdk/issues/12398) it was thought this Gordian knot could be
|
||||
unwound by mocking all dependencies in the test phase for each module, but seeing how these
|
||||
refactors were complete rewrites of test suites discussions began around the fate of the
|
||||
existing integration tests. One perspective is that they ought to be thrown out, another is
|
||||
existing integration tests. One perspective is that they ought to be thrown out, another is
|
||||
that integration tests have some utility of their own and a place in the SDK's testing story.
|
||||
|
||||
Another point of confusion has been the current state of CLI test suites, [x/auth](https://github.com/cosmos/cosmos-sdk/blob/0f7e56c6f9102cda0ca9aba5b6f091dbca976b5a/x/auth/client/testutil/suite.go#L44-L49) for
|
||||
example. In code these are called integration tests, but in reality function as end to end
|
||||
tests by starting up a tendermint node and full application. [EPIC: Rewrite and simplify
|
||||
example. In code these are called integration tests, but in reality function as end to end
|
||||
tests by starting up a tendermint node and full application. [EPIC: Rewrite and simplify
|
||||
CLI tests](https://github.com/cosmos/cosmos-sdk/issues/12696) identifies the ideal state of CLI tests using mocks, but does not address the
|
||||
place end to end tests may have in the SDK.
|
||||
|
||||
@@ -43,8 +43,8 @@ ideal state in the SDK.
|
||||
### Unit tests
|
||||
|
||||
Unit tests exercise the code contained in a single module (e.g. `/x/bank`) or package
|
||||
(e.g. `/client`) in isolation from the rest of the code base. Within this we identify two
|
||||
levels of unit tests, *illustrative* and *journey*. The definitions below lean heavily on
|
||||
(e.g. `/client`) in isolation from the rest of the code base. Within this we identify two
|
||||
levels of unit tests, *illustrative* and *journey*. The definitions below lean heavily on
|
||||
[The BDD Books - Formulation](https://leanpub.com/bddbooks-formulation) section 1.3.
|
||||
|
||||
*Illustrative* tests exercise an atomic part of a module in isolation - in this case we
|
||||
@@ -65,11 +65,11 @@ supplied to the keeper constructor.
|
||||
|
||||
#### Limitations
|
||||
|
||||
Certain modules are tightly coupled beyond the test phase. A recent dependency report for
|
||||
Certain modules are tightly coupled beyond the test phase. A recent dependency report for
|
||||
`bank -> auth` found 274 total usages of `auth` in `bank`, 50 of which are in
|
||||
production code and 224 in test. This tight coupling may suggest that either the modules
|
||||
production code and 224 in test. This tight coupling may suggest that either the modules
|
||||
should be merged, or refactoring is required to abstract references to the core types tying
|
||||
the modules together. It could also indicate that these modules should be tested together
|
||||
the modules together. It could also indicate that these modules should be tested together
|
||||
in integration tests beyond mocked unit tests.
|
||||
|
||||
In some cases setting up a test case for a module with many mocked dependencies can be quite
|
||||
@@ -82,18 +82,18 @@ Integration tests define and exercise relationships between an arbitrary number
|
||||
and/or application subsystems.
|
||||
|
||||
Wiring for integration tests is provided by `depinject` and some [helper code](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/testutil/sims/app_helpers.go#L95) starts up
|
||||
a running application. A section of the running application may then be tested. Certain
|
||||
a running application. A section of the running application may then be tested. Certain
|
||||
inputs during different phases of the application life cycle are expected to produce
|
||||
invariant outputs without too much concern for component internals. This type of black box
|
||||
invariant outputs without too much concern for component internals. This type of black box
|
||||
testing has a larger scope than unit testing.
|
||||
|
||||
Example 1 [client/grpc_query_test/TestGRPCQuery](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/client/grpc_query_test.go#L111-L129) - This test is misplaced in `/client`,
|
||||
but tests the life cycle of (at least) `runtime` and `bank` as they progress through
|
||||
startup, genesis and query time. It also exercises the fitness of the client and query
|
||||
startup, genesis and query time. It also exercises the fitness of the client and query
|
||||
server without putting bytes on the wire through the use of [QueryServiceTestHelper](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/baseapp/grpcrouter_helpers.go#L31).
|
||||
|
||||
Example 2 `x/evidence` Keeper integration tests - Starts up an application composed of [8
|
||||
modules](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/evidence/testutil/app.yaml#L1) with [5 keepers](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/evidence/keeper/keeper_test.go#L101-L106) used in the integration test suite. One test in the suite
|
||||
modules](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/evidence/testutil/app.yaml#L1) with [5 keepers](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/evidence/keeper/keeper_test.go#L101-L106) used in the integration test suite. One test in the suite
|
||||
exercises [HandleEquivocationEvidence](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/x/evidence/keeper/infraction_test.go#L42) which contains many interactions with the staking
|
||||
keeper.
|
||||
|
||||
@@ -103,10 +103,10 @@ YAML as above) [statically](https://github.com/cosmos/cosmos-sdk/blob/main/x/nft
|
||||
#### Limitations
|
||||
|
||||
Setting up a particular input state may be more challenging since the application is
|
||||
starting from a zero state. Some of this may be addressed by good test fixture
|
||||
abstractions with testing of their own. Tests may also be more brittle, and larger
|
||||
starting from a zero state. Some of this may be addressed by good test fixture
|
||||
abstractions with testing of their own. Tests may also be more brittle, and larger
|
||||
refactors could impact application initialization in unexpected ways with harder to
|
||||
understand errors. This could also be seen as a benefit, and indeed the SDK's current
|
||||
understand errors. This could also be seen as a benefit, and indeed the SDK's current
|
||||
integration tests were helpful in tracking down logic errors during earlier stages
|
||||
of app-wiring refactors.
|
||||
|
||||
@@ -114,38 +114,38 @@ of app-wiring refactors.
|
||||
|
||||
Simulations (also called generative testing) are a special case of integration tests where
|
||||
deterministically random module operations are executed against a running simapp, building
|
||||
blocks on the chain until a specified height is reached. No *specific* assertions are
|
||||
blocks on the chain until a specified height is reached. No *specific* assertions are
|
||||
made for the state transitions resulting from module operations but any error will halt and
|
||||
fail the simulation. Since `crisis` is included in simapp and the simulation runs
|
||||
fail the simulation. Since `crisis` is included in simapp and the simulation runs
|
||||
EndBlockers at the end of each block any module invariant violations will also fail
|
||||
the simulation.
|
||||
|
||||
Modules must implement [AppModuleSimulation.WeightedOperations](https://github.com/cosmos/cosmos-sdk/blob/2bec9d2021918650d3938c3ab242f84289daef80/types/module/simulation.go#L31) to define their
|
||||
simulation operations. Note that not all modules implement this which may indicate a
|
||||
simulation operations. Note that not all modules implement this which may indicate a
|
||||
gap in current simulation test coverage.
|
||||
|
||||
Modules not returning simulation operations:
|
||||
Modules not returning simulation operations:
|
||||
|
||||
- `auth`
|
||||
- `capability`
|
||||
- `evidence`
|
||||
- `mint`
|
||||
- `params`
|
||||
* `auth`
|
||||
* `capability`
|
||||
* `evidence`
|
||||
* `mint`
|
||||
* `params`
|
||||
|
||||
A separate binary, [runsim](https://github.com/cosmos/tools/tree/master/cmd/runsim), is responsible for kicking off some of these tests and
|
||||
managing their life cycle.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- [A success](https://github.com/cosmos/cosmos-sdk/runs/7606931983?check_suite_focus=true) may take a long time to run, 7-10 minutes per simulation in CI.
|
||||
- [Timeouts](https://github.com/cosmos/cosmos-sdk/runs/7606932295?check_suite_focus=true) sometimes occur on apparent successes without any indication why.
|
||||
- Useful error messages not provided on [failure](https://github.com/cosmos/cosmos-sdk/runs/7606932548?check_suite_focus=true) from CI, requiring a developer to run
|
||||
* [A success](https://github.com/cosmos/cosmos-sdk/runs/7606931983?check_suite_focus=true) may take a long time to run, 7-10 minutes per simulation in CI.
|
||||
* [Timeouts](https://github.com/cosmos/cosmos-sdk/runs/7606932295?check_suite_focus=true) sometimes occur on apparent successes without any indication why.
|
||||
* Useful error messages not provided on [failure](https://github.com/cosmos/cosmos-sdk/runs/7606932548?check_suite_focus=true) from CI, requiring a developer to run
|
||||
the simulation locally to reproduce.
|
||||
|
||||
### E2E tests
|
||||
|
||||
End to end tests exercise the entire system as we understand it in as close an approximation
|
||||
to a production environment as is practical. Presently these tests are located at
|
||||
to a production environment as is practical. Presently these tests are located at
|
||||
[tests/e2e](https://github.com/cosmos/cosmos-sdk/tree/main/tests/e2e) and rely on [testutil/network](https://github.com/cosmos/cosmos-sdk/tree/main/testutil/network) to start up an in-process Tendermint node.
|
||||
|
||||
#### Limitations
|
||||
@@ -164,13 +164,13 @@ The scope of e2e tests has been complected with command line interface testing.
|
||||
We accept these test scopes and identify the following decisions points for each.
|
||||
|
||||
| Scope | App Fixture | Mocks? |
|
||||
|-------------|-------------|--------|
|
||||
| ----------- | ----------- | ------ |
|
||||
| Unit | None | Yes |
|
||||
| Integration | depinject | Some |
|
||||
| Simulation | simapp | No |
|
||||
| Simulation | depinject | No |
|
||||
| E2E | simapp | No |
|
||||
|
||||
#### Unit Tests
|
||||
### Unit Tests
|
||||
|
||||
All modules must have mocked unit test coverage.
|
||||
|
||||
@@ -185,11 +185,11 @@ production code.
|
||||
|
||||
When module unit test introduction as per [EPIC: Unit testing of modules via mocks](https://github.com/cosmos/cosmos-sdk/issues/12398)
|
||||
results in a near complete rewrite of an integration test suite the test suite should be
|
||||
retained and moved to `/tests/integration`. We accept the resulting test logic
|
||||
retained and moved to `/tests/integration`. We accept the resulting test logic
|
||||
duplication but recommend improving the unit test suite through the addition of
|
||||
illustrative tests.
|
||||
|
||||
#### Integration Tests
|
||||
### Integration Tests
|
||||
|
||||
All integration tests shall be located in `/tests/integration`, even those which do not
|
||||
introduce extra module dependencies.
|
||||
@@ -199,11 +199,11 @@ modules in application startup, i.e. don't depend on simapp.
|
||||
|
||||
Integration tests should outnumber e2e tests.
|
||||
|
||||
#### Simulations
|
||||
### Simulations
|
||||
|
||||
Simulations shall startup and test simapp directly.
|
||||
Simulations shall use `depinject`. They are located under `/x/{moduleName}/simulation`.
|
||||
|
||||
#### E2E Tests
|
||||
### E2E Tests
|
||||
|
||||
Existing e2e tests shall be migrated to integration tests by removing the dependency on the
|
||||
test network and in-process Tendermint node to ensure we do not lose test coverage.
|
||||
@@ -220,22 +220,22 @@ demonstrated in [PR#12706](https://github.com/cosmos/cosmos-sdk/pull/12706).
|
||||
|
||||
### Positive
|
||||
|
||||
- test coverage is increased
|
||||
- test organization is improved
|
||||
- reduced dependency graph size in modules
|
||||
- simapp removed as a dependency from modules
|
||||
- inter-module dependencies introduced in test code are removed
|
||||
- reduced CI run time after transitioning away from in process Tendermint
|
||||
* test coverage is increased
|
||||
* test organization is improved
|
||||
* reduced dependency graph size in modules
|
||||
* simapp removed as a dependency from modules
|
||||
* inter-module dependencies introduced in test code are removed
|
||||
* reduced CI run time after transitioning away from in process Tendermint
|
||||
|
||||
### Negative
|
||||
|
||||
- some test logic duplication between unit and integration tests during transition
|
||||
- test written using dockertest DX may be a bit worse
|
||||
* some test logic duplication between unit and integration tests during transition
|
||||
* test written using dockertest DX may be a bit worse
|
||||
|
||||
### Neutral
|
||||
|
||||
- learning curve for BDD style tests
|
||||
- some discovery required for e2e transition to dockertest
|
||||
* learning curve for BDD style tests
|
||||
* some discovery required for e2e transition to dockertest
|
||||
|
||||
## Further Discussions
|
||||
|
||||
@@ -243,8 +243,8 @@ It may be useful if test suites could be run in integration mode (with mocked te
|
||||
with e2e fixtures (with real tendermint and many nodes). Integration fixtures could be used
|
||||
for quicker runs, e2e fixures could be used for more battle hardening.
|
||||
|
||||
A PoC `x/gov` was completed in PR [#12847](https://github.com/cosmos/cosmos-sdk/pull/12847)
|
||||
is in progress for unit tests demonstrating BDD.
|
||||
A PoC `x/gov` was completed in PR [#12847](https://github.com/cosmos/cosmos-sdk/pull/12847)
|
||||
is in progress for unit tests demonstrating BDD [Rejected].
|
||||
Observing that a strength of BDD specifications is their readability, and a con is the
|
||||
cognitive load while writing and maintaining, current consensus is to reserve BDD use
|
||||
for places in the SDK where complex rules and module interactions are demonstrated.
|
||||
|
||||
Reference in New Issue
Block a user