Tari is going green
BDD Testing with Cucumber
Tari is going green!
No, we’re not switching to Proof of Stake. (LOL - as if that would make a difference).
But we are using Cucumber for Behavior Driven Development (BDD).
You may have noticed a lot of PR’s and commits with the word “cucumber” in them. Tari uses Cucumber, and specifically Cucumber.js to easily specify test scenarios in plain text. The tests can be found under the integration_tests/features folder. The tests spin up base nodes, merge mining proxies and miners in a local, low difficulty network and interact with them via GRPC, simulating various scenarios that might happen on testnet.
The plain text method of specifying tests makes it easy to read, write and verify correctness of the tests.
Here’s a simple example that tests submitting blocks:
Scenario: Mining example
Given I have 3 seed nodes
And I have a base node NODE_A connected to all seed nodes
When I mine 20 blocks on NODE_A
Then all nodes are at height 20
In Cucumber tests, each line is a step, and will start with one of Given
, When
or Then
. And
can also be used to make the test easier to read, in which case it
uses the keyword from the previous step. The Given
keyword is used to set up the scenario, When
is used to describe an action being performed, and Then
is used to test
whether what we expected to happen, happened. (Learn more about Gherkin syntax)
In the above example we first set up 3 seed nodes. Every scenario runs in its own isolated local network, so in this case, we start by creating 3 nodes. When the test runs, it will run this Javascript definition found in integration_tests/features/support/steps.js:
Given('I have {int} seed nodes', async function (n) {
...
});
Note: You don’t need to know Javascript to write tests as long as you’re using existing steps definitions, and there are a lot of those already defined.
...
And I have a base node NODE_A connected to all seed nodes
When I mine 20 blocks on NODE_A
...
In the next two steps we create a base node and name it NODE_A
and then mine 20 blocks. The difficulty for this network is capped with a low maximum that allows us to create
blocks very quickly. When the test runs, 20 blocks will be created and submitted to NODE_A
.
...
Then all nodes are at height 20
The last step we check that network behaved as we expected it to. We’re expecting that the blocks were propagated to all four nodes on the network. If any of the nodes is not at height 20, the test will fail. For those interested, here’s the simplified Javascript step definition that runs:
Then('all nodes are at height {int}', async function (height) {
await this.forEachClientAsync(async (client, name) => {
const currTip = await client.getTipHeight();
expect(currTip).to.equal(height);
})
});
Instructions on running the tests are available in the README in the integration_tests
folder.
The tests verify many scenarios, including transaction propagation, re-orgs, block propagation and syncing, and even sending thousands of transactions.
There’s not much more to it, and this is a really simple entry point to contribute. If you get stuck, pop into the #tari-dev IRC on freenode Libera.Chat and ask a question.