For a function or system that has `n` conditions, a Decision Table is an enumeration of all possible combinations of input conditions and associated outcomes. Complete Decision Table testing involves testing each of the `2^n` conditions. Decision Tables don't only apply to functions with boolean inputs, instead synthetic conditions can be identified from the tester. For example one condition could be the inclusion of a variable in an equivalence class (see [Equivalence Partitioning](/codex/equivalence-partitioning)).
### Collapsed Decision Table
Depending on the context, some combinations of input values may not be meaningfully different and therefore may be excluded from the decision table at the discretion of the tester.
### Worked example
Let's look at the OpenZeppelin ERC20 `transferFrom` implementation.
-- CODE language-solidity --
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
A set of conditions for this function could be identified as follows:
- Valid sender: `sender != 0x0`
- Valid recipient: `recipient != 0x0`
- Sufficient sender funds: `balanceOf(sender)` >= `amount`
- Sufficient sender allowance: `allowances(sender, recipient)` >= `amount`
The full Decision Table would have 16 entries but we could form a smaller table by collapsing cases where the sender and recipient addresses are invalid. We get the following decision table consisting of 6 possible test cases:
- Invalid sender ⇒ failure
- Invalid recipient ⇒ failure
- Valid sender & recipient:
- Sufficient sender funds, Sufficient sender allowance ⇒ success, balance and allowance updated
- Sufficient sender funds, Insufficient sender allowance ⇒ failure
- Insufficient sender funds, Sufficient sender allowance ⇒ failure
- Insufficient sender funds, Insufficient sender allowance ⇒ failure.