Decision/Branch is a heuristic to identify new test cases based on the evaluation of branches. The existing test suite is analyzed for coverage. Any logical branch which could resolve in branching of control flow or errors is evaluated for all possible outcomes. If an outcome is not covered in the test suite, a new test case can be developed which tests the branch. Branch coverage is a stricter form of statement coverage.
Consider the OpenZeppelin deploy function below in the Create2 library:
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(
uint256 amount,
bytes32 salt,
bytes memory bytecode
) internal returns (address) {
address addr;
require(address(this).balance >= amount, "Create2: insufficient balance");
require(bytecode.length != 0, "Create2: bytecode length is zero");
assembly {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
}
require(addr != address(0), "Create2: Failed on deploy");
return addr;
}This code has 3 branches/decision points:
address(this).balance>=amountor the oppositebytecode.length != 0or the oppositeaddr != address(0)or the opposite
- The
brownieframework provides branch coverage information: https://medium.com/coinmonks/brownie-evaluating-solidity-code-coverage-via-opcode-tracing-a7cf5a92d28c