Protocol Interface Testing is a heuristic to identify more test cases by studying the contract calls to external protocols.
For each interaction with an external protocol, Protocol Interface Testing aims to apply techniques like [Equivalence Partitioning](/codex/equivalence-partitioning) and [Boundary Value Analysis](/codex/boundary-value-analysis) to test a wide range of possible inputs, outputs and effects. This approach is equivalent to Inter-component testing in traditional testing literature.
### Worked example
Consider the `release` function by OpenZeppelin in `PaymentSplitter`.
-- CODE language-solidity --
/**
* @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
* percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
* contract.
*/
function release(IERC20 token, address account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
uint256 payment = _pendingPayment(account, totalReceived, released(token, account));
require(payment != 0, "PaymentSplitter: account is not due payment");
_erc20Released[token][account] += payment;
_erc20TotalReleased[token] += payment;
SafeERC20.safeTransfer(token, account, payment);
emit ERC20PaymentReleased(token, account, payment);
}
It has two external calls:
- `uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);`
- `SafeERC20.safeTransfer(token, account, payment);` .
Each of which could be tested under a range of possible inputs.