A simple, fast, and easy-to-use Solidity test generator based on the Branching Tree Technique.
bash
cargo install bulloak
Say you have a foo.tree file with the following contents:
text
FooTest
└── When stuff called
└── It should revert.
If you pass it to bulloak like so, you will get the skeleton
of a test contract printed to stdout:
``` $ bulloak foo.tree pragma solidity 0.8.0;
contract FooTest { modifier whenStuffCalled() { _; }
function testRevertWhenStuffCalled() external whenStuffCalled { // It should revert. } } ```
If you are working in a solidity project and you have
multiple trees you want to scaffold, you can use the -w option.
$ bulloak -w ./**/*.tree
This will create solidity files with the same name as the .tree
files with the result of scaffolding each tree.
If there exists a file with a title that matches the name at the
root node of the .tree, then bulloak will skip writing that file.
However, you may override this behaviour with the -f flag. This
will write to the filesystem overwriting any files that exist.
$ bulloak -wf ./**/*.tree
Another feature of bulloak is reporting errors in your input trees.
For example, say you have a buggy foo.tree file, which is missing a
└ character. Running bulloak foo.tree would report the error like this:
``
•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
bulloak error: unexpectedwhen` keyword
── when the id references a null stream ^^^^
--- (line 2, column 4) --- file: foo.tree ```
``` Usage: bulloak [OPTIONS] [FILES]...
Arguments: [FILES]... .tree files to process
Options:
-c
Whether to print it branches as comments in the output code
-i write_files is specified, use --force-write to overwrite the output files
-s, --solidity-version
bulloak scaffolds solidity test files based on .tree specifications
that follow the Branching Tree Technique.
Currently, there is on-going discussion on how to handle different edge-cases to better empower the solidity community. This section is a description of the current implementation of the compiler.
when/given branches of a tree.it branches of a tree. Every action is a leaf node of the tree.Each tree file should describe a function under test. Trees follow these rules:
bulloak expects you to use ├ and └ characters to denote branches.when, given or it.when or given, it is a condition.when and given are interchangeable.it, it is an action.it is the same as It and IT.Take the following solidity function:
solidity
function hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? hash(a, b) : hash(b, a);
}
A reasonable spec for the above function would be:
HashPairTest
├── It should never revert.
├── When first arg is smaller than second arg
│ └── It should match the result of `keccak256(abi.encodePacked(a,b))`.
└── When first arg is bigger than second arg
└── It should match the result of `keccak256(abi.encodePacked(b,a))`.
There is a top-level action which would generate a test to check the function invariant that it should never revert.
Then, we have the two possible preconditions: a < b and a >= b. Both branches end in an action that will make bulloak generate the respective test.
Note the following things:
bulloak also supports actions with sibling conditions, but this might get removed in a future version per this discussion.There are a few things to keep in mind about the scaffolded solidity test:
.tree but with a .t.sol extension. E.g. test.tree would correspond to test.t.sol..tree file.Please refer to CONTRIBUTING.md.
This project is licensed under either of: