Testing is a critical part of any library which wishes to remain secure, safe and reliable.
Ethers currently has over 23k tests among its test suites, which are all made available for other projects to use as simple exported GZIP-JSON files.
The tests are run on every check-in and the results can been seen on the GitHub CI Action.
We also strive to constantly add new test cases, especially when issues arise to ensure the issue is present prior to the fix, corrected after the fix and included to prevent future changes from causing a regression.
A large number of the test cases were created procedurally by using known correct implementations from various sources (such as Geth) and written in different languages and verified with multiple libraries.
For example, the ABI test suites were generated by procedurally generating a list of types, for each type choosing a random (valid) value, which then was converted into a Solidity source file, compiled using solc and deployed to a running Parity node and executed, with its outputs being captured. Similar to the how many of the hashing, event and selector test cases were created.
While web technologies move quite fast, especially in the Web3 universe, we try to keep ethers as accessible as possible.
Currently ethers should work on almost any ES3 or better environment and tests are run against:
- node.js 8.x
- node.js 10.x
- node.js 12.x
- node.js 13.x
- Web Browsers (using UMD)
- Web Browsers (using ES modules)
If there is an environment you feel has been overlooked or have suggestions, please feel free to reach out by opening an issue on Github.
We would like to add a test build for Expo and React as those developers often seem to encounter pain points when using ethers, so if you have experience or ideas on this, bug us.
The next Major version (probably summer 2021) will likely drop support for node 8.x and will require ES2015 for Proxy.
Certain features in JavaScript are also avoided, such as look-behind tokens in regular expressions, since these have caused conflicts (at import time) with certain JavaScript environments such as Otto.
Basically, the moral of the story is "be inclusive and don't drop people needlessly".
The test suites are available as gzipped JSON files in the @ethersproject/testcases, which makes it easy to install and import (both GZIP and JSON are quite easy to consume from most languages). Each test suite also has its schema available in this package.
| Filename | Test Cases | ||
| accounts.json.gz | Private Keys and addresses in checksum and ICAP formats | ||
| contract-events.json.gz | Compiled Solidity, ABI interfaces, input types/values with the output types/values for emitted events; all tests were executed against real Ethereum nodes | ||
| contract-interface.json.gz | Compiled Solidity, ABI interfaces, input types/values with the output types/values, encoded and decoded binary data and normalized values for function calls executed against real Ethereum nodes. | ||
| contract-interface-abi2.json.gz | Identical to contract-interface, except with emphasis on the ABIv2 coder which supports nested dynami types and structured data | ||
| contract-signatures.json.gz | Contract signatures and matching selectors | ||
| hashes.json.gz | Data and respective hashes against a variety of hash functions | ||
| hdnode.json.gz | HDNodes (BIP-32) with mnemonics, entropy, seed and computed nodes with pathes and addresses | ||
| namehash.json.gz | ENS names along with computed [namehashes](link-namehash | ||
| nameprep.json.gz | IDNA and Nameprep representations including official vectors | ||
| rlp-coder.json.gz | Recursive-Length Prefix (RLP) data and encodings | ||
| solidity-hashes.json.gz | Hashes based on the Solidity non-standard packed form | ||
| transactions.json.gz | Signed and unsigned transactions with their serialized formats including both with and without EIP-155 replay protection | ||
| units.json.gz | Values converted between various units | ||
| wallets.json.gz | Keystore JSON format wallets, passwords and decrypted values | ||
| wordlists.json.gz | Fully decompressed BIP-39 official wordlists | ||
| Test Suites | |||
There are also convenience functions for those developing directly in TypeScript.
Load all the given testcases for the tag.
A tag is the string in the above list of test case names not including any extension (e.g. "solidity-hashes")
Most testcases have its schema available as a TypeScript type to make testing each property easier.
When creating test cases, often we want want random data from the perspective we do not case what values are used, however we want the values to be consistent across runs. Otherwise it becomes difficult to reproduce an issue.
In each of the following the seed is used to control the random value returned. Be sure to tweak the seed properly, for example on each iteration change the value and in recursive functions, concatenate to the seed.
Return at least lower random bytes, up to upper (exclusive) if specified, given seed. If upper is omitted, exactly /lower bytes are returned.
Identical to randomBytes, except returns the value as a DataHexString instead of a Uint8Array.
Returns a random number of at least lower and less than upper given seed.