测试是任何希望保持安全、安全和可靠的库的关键部分。
Ethers目前有超过23000个测试在它的测试套件中, 这些测试都可以作为简单的GZIP-JSON导出文件供其他项目使用。。
每次签入都要运行测试并且结果可以在GitHub CI Action上查看
我们还努力不断地添加新的测试用例,特别是当问题出现时,以确保问题出现在修复之前,在修复之后得到纠正,并包括进来以防止未来的变更导致回退。
大量测试用例是通过使用来自不同的资源(例如Geth)已知正确的实现程序创建的,并且用不同的语言编写,使用多个库进行验证
例如, ABI测试套件是通过程序生成的类型列表来生成的, 对于每个选择随机(有效)值, 然后将其转换成一个Solidity源文件, 使用solc
编译,部署到一个运行的Parity节点并且执行,然后捕获它的输出。类似于创建了多少的哈希、事件和选择器测试用例。 cases were created.
虽然网络技术发展很快,特别是在Web3领域,但我们尽量保持ether的可访问性。
目前ether应该可以在几乎所有ES3或更好的环境下工作,并在以下环境下运行测试:
- 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)
如果你觉得有一个环境被忽视了或有建议,请随时打开一个issue on Github.
我们想为Expo和React添加一个测试版本 因为那些开发人员在使用ethers时经常遇到麻烦,所以你对此有经验或者想法,bug us.
下一个主要版本(可能在2021年夏天)将可能回取消对node 8.x的支持,并且将需要ES2015的代理.
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".
测试套件在@ethersproject/testcases
中以GZIP格式提供, 这使得安装和导入比较容易(GZIP和JSON在大多数语言中都很容易使用)。每个测试套件在这个包中也有其可用的模式。
文件名称 | 测试用例 | |
accounts.json.gz | Private Keys and addresses in checksum and ICAP formats | |
contract-events.json.gz | 已经编译的Solidity,ABI接口, 输入类型/值与输出类型/值的emitted事件;所有测试都是针对真实的Ethereum节点执行的。 | |
contract-interface.json.gz | 已经编译的Solidity, ABI接口, 输入类型/值与输出类型/值、编码和解码的二进制数据以及针对真实Ethereum节点执行的函数调用的标准化值。 | |
contract-interface-abi2.json.gz | 和合约-接口 一样, except with emphasis on the ABIv2 coder which supports nested dynami types and structured data | |
contract-signatures.json.gz | 合同签名和匹配的选择器 | |
hashes.json.gz | 针对各种哈希函数的数据和各自的哈希值 | |
hdnode.json.gz | HDNodes (BIP-32) with mnemonics, entropy, seed and computed nodes with pathes and addresses 带有助记符、entropy、seed和带有路径和地址的计算节点的hdnode (BIP-32) | |
namehash.json.gz | ENS名称与计算的namehashes | |
nameprep.json.gz | IDNA和Nameprep表示法,包括官方矢量 | |
rlp-coder.json.gz | 递归长度前缀(RLP)数据和编码 | |
solidity-hashes.json.gz | 基于Solidity非标准打包形式的哈希值 | |
transactions.json.gz | 带有序列化格式的已签名和未签名交易,包括带有和不带有EIP-155重放保护的交易 | |
units.json.gz | 不同单位之间转换的值 | |
wallets.json.gz | Keystore JSON格式的钱包、密码和解密值 | |
wordlists.json.gz | 完全解压的BIP-39官方词汇表 | |
测试组件套 | |
对于那些直接使用Typescript进行开发的人来说,这里有一些方便的功能
testcases.loadTests( tag ) ⇒ Array< TestCase > 加载所有给定tag的测试用例.
标签是上述测试用例名称列表中的字符串,不包括任何扩展名(e.g. "solidity-hashes"
)
testcases.TestCase.TEST_NAME 大多数测试案例都有它的模式,可作为TypeScript类型,使测试每个属性更容易。
Deterministic Random Numbers (DRNG)
当创建测试用例时,我们通常希望从我们不确定使用了什么值的角度获得随机数据,但是我们希望这些值在运行时保持一致。否则就很难重现问题。
在下面的每一个示例中,seed用于控制返回的随机值。确保正确地调整seed,例如在每次迭代中更改值,并在递归函数中连接到seed。
testcases.randomBytes( seed , lower [ , upper ] ) ⇒ Uint8Array Return at least lower random bytes, up to upper (exclusive) if specified, given seed. If upper is omitted, exactly /lower bytes are returned.
testcases.randomNumber( seed , lower , upper ) ⇒ number Returns a random number of at least lower and less than upper given seed.
本节仍在进行中,但将概述测试用例及其值的一些更微妙的方面。
在下一个主要版本中,可能会对测试用例进行彻底的检查,使代码覆盖测试更直接,并消除一些冗余。
例如,不再需要分离ABI和ABIv2测试用例,帐户和交易套件可以合并到一个大型集合中。
使用私钥的基本账户信息和计算各种地址形式。
测试时通过[EthereumJS](https://github.com/ethereumjs)和创建的自定义脚本来直接与Geth和cpp实现进行交互来验证的。
请查看: accounts.json.gz
属性 | 意义 | |
name | 测试案例的名称 | |
privateKey | 私钥 | |
address | 地址(消协) | |
checksumAddress | 有校验和调整的情况下的地址 | |
icapAddress | ICAP地址 | |
属性 | |
{
"name": "random-1023",
"address": "0x53bff74b9af2e3853f758a8d2bd61cd115d27782",
"privateKey": "0x8ab0e165c2ea461b01cdd49aec882d179dccdbdb5c85c3f9c94c448aa65c5ace",
"checksumAddress": "0x53bFf74b9Af2E3853f758A8D2Bd61CD115d27782",
"icapAddress": "XE709S6NUSJR6SXQERCMYENAYYOZ2Y91M6A"
}
程序化生成测试用例,用于测试ABI编码。
{
"name": "random-1999",
"source": "contract Test {\n function test() constant returns (address, bool, bytes14[1]) {\n address a = address(0x061C7F399Ee738c97C7b7cD840892B281bf772B5);\n bool b = bool(true);\n bytes14[1] memory c;\n c[0] = bytes14(0x327621c4abe12d4f21804ed40455);\n return (a, b, c);\n }\n}\n",
"types": "[\"address\",\"bool\",\"bytes14[1]\"]",
"interface": "[{\"constant\":true,\"inputs\":[],\"name\":\"test\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"bool\"},{\"name\":\"\",\"type\":\"bytes14[1]\"}],\"type\":\"function\"}]\n",
"bytecode": "0x6060604052610175806100126000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063f8a8fd6d1461003957610037565b005b610046600480505061009d565b604051808473ffffffffffffffffffffffffffffffffffffffff1681526020018315158152602001826001602002808383829060006004602084601f0104600f02600301f150905001935050505060405180910390f35b600060006020604051908101604052806001905b60008152602001906001900390816100b157905050600060006020604051908101604052806001905b60008152602001906001900390816100da5790505073061c7f399ee738c97c7b7cd840892b281bf772b59250600191506d327621c4abe12d4f21804ed404557201000000000000000000000000000000000000028160006001811015610002579090602002019071ffffffffffffffffffffffffffffffffffff191690818152602001505082828295509550955061016d565b50505090919256",
"result": "0x000000000000000000000000061c7f399ee738c97c7b7cd840892b281bf772b50000000000000000000000000000000000000000000000000000000000000001327621c4abe12d4f21804ed40455000000000000000000000000000000000000",
"values": "[{\"type\":\"string\",\"value\":\"0x061C7F399Ee738c97C7b7cD840892B281bf772B5\"},{\"type\":\"boolean\",\"value\":true},[{\"type\":\"buffer\",\"value\":\"0x327621c4abe12d4f21804ed40455\"}]]",
"normalizedValues": "[{\"type\":\"string\",\"value\":\"0x061C7F399Ee738c97C7b7cD840892B281bf772B5\"},{\"type\":\"boolean\",\"value\":true},[{\"type\":\"buffer\",\"value\":\"0x327621c4abe12d4f21804ed40455\"}]]",
"runtimeBytecode": "0x60606040526000357c010000000000000000000000000000000000000000000000000000000090048063f8a8fd6d1461003957610037565b005b610046600480505061009d565b604051808473ffffffffffffffffffffffffffffffffffffffff1681526020018315158152602001826001602002808383829060006004602084601f0104600f02600301f150905001935050505060405180910390f35b600060006020604051908101604052806001905b60008152602001906001900390816100b157905050600060006020604051908101604052806001905b60008152602001906001900390816100da5790505073061c7f399ee738c97c7b7cd840892b281bf772b59250600191506d327621c4abe12d4f21804ed404557201000000000000000000000000000000000000028160006001811015610002579090602002019071ffffffffffffffffffffffffffffffffffff191690818152602001505082828295509550955061016d565b50505090919256"
}
计算的ABI签名和选择器哈希值。
{
"name": "random-1999",
"sigHash": "0xf51e9244",
"abi": "[{\"constant\":false,\"inputs\":[{\"name\":\"r0\",\"type\":\"string[2]\"},{\"name\":\"r1\",\"type\":\"uint128\"},{\"components\":[{\"name\":\"a\",\"type\":\"bytes\"},{\"name\":\"b\",\"type\":\"bytes\"},{\"name\":\"c\",\"type\":\"bytes\"}],\"name\":\"r2\",\"type\":\"tuple\"},{\"name\":\"r3\",\"type\":\"bytes\"}],\"name\":\"testSig\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"test\",\"outputs\":[{\"name\":\"r0\",\"type\":\"string[2]\"},{\"name\":\"r1\",\"type\":\"uint128\"},{\"components\":[{\"name\":\"a\",\"type\":\"bytes\"},{\"name\":\"b\",\"type\":\"bytes\"},{\"name\":\"c\",\"type\":\"bytes\"}],\"name\":\"r2\",\"type\":\"tuple\"},{\"name\":\"r3\",\"type\":\"bytes\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]",
"signature": "testSig(string[2],uint128,(bytes,bytes,bytes),bytes)"
}
{
"data": "0x3718a88ceb214c1480c32a9d",
"keccak256": "0x82d7d2dc3d384ddb289f41917b8280675bb1283f4fe2b601ac7c8f0a2c2824fa",
"sha512": "0xe93462bb1de62ba3e6a980c3cb0b61728d3f771cea9680b0fa947b6f8fb2198a2690a3a837495c753b57f936401258dfe333a819e85f958b7d786fb9ab2b066c",
"sha256": "0xe761d897e667aa72141dd729264c393c4ddda5c62312bbd21b0f4d954eba1a8d"
}
BIP-32 HD Wallets的测试用例
{
"name": "trezor-23",
"entropy": "0xf585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
"mnemonic": "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold",
"locale": "en",
"password": "TREZOR",
"hdnodes": [
{
"path": "m",
"address": "0xfd8eb95169ce57eab52fb69bc6922e9b6454d9aa",
"privateKey": "0x679bf92c04cf16307053cbed33784f3c4266b362bf5f3d7ee13bed6f2719743c"
},
{
"address": "0xada964e9f10c4fc9787f9e17f00c63fe188722b0",
"privateKey": "0xdcbcb48a2b11eef0aab93a8f88d83f60a3aaabb34f9ffdbe939b8f059b30f2b7",
"path": "m/8'/8'/2/3/4"
},
{
"privateKey": "0x10fd3776145dbeccb3d6925e4fdc0d58b452fce40cb8760b12f8b4223fafdfa6",
"address": "0xf3f6b1ef343d5f5f231a2287e801a46add43eb06",
"path": "m/1'/3'"
},
{
"address": "0xb7b0fdb6e0f79f0529e95400903321e8a601b411",
"privateKey": "0x093a8ff506c95a2b79d397aed59703f6212ff3084731c2f03089b069ae76e69d",
"path": "m/8'/4'/7'"
},
{
"path": "m/7'/5'/11",
"privateKey": "0x6bd79da4dfa7dd0abf566a011bdb7cba0d28bba9ca249ba25880d5dabf861b42",
"address": "0x1b3ad5fa50ae32875748107f4b2160829cc10536"
},
{
"path": "m/9'/6'/2'/7'/3'",
"address": "0x42eb4bed59f3291d02387cf0fb23098c55d82611",
"privateKey": "0xfc173acba7bc8bb2c434965d9e99f5a221f81add421bae96a891d08d60be11dd"
}
],
"seed": "0x01f5bced59dec48e362f2c45b5de68b9fd6c92c6634f44d6d40aab69056506f0e35524a518034ddc1192e1dacd32c1ed3eaa3c3b131c88ed8e7e54c49a5d0998"
}
ENS Namehash Algorithm的测试用例
{
"expected": "0x33868cc5c3fd3a9cd3adbc1e868ea133d2218f60dc2660c3bc48d8b1f4961384",
"name": "ViTalIk.WALlet.Eth",
"test": "mixed case"
}
{
"name": "arrayWithNullString3",
"encoded": "0xc3808080",
"decoded": [ "0x", "0x", "0x" ]
}
对Solidity哈希函数非标准打包形式的测试
这些测试是通过程序化地生成随机签名和与这些签名相匹配的值,构建等价的Soldity,将其编译并部署到一个Parity节点,然后评估响应。
{
"name": "random-1999",
"keccak256": "0x7d98f1144a0cd689f720aa2f11f0a73bd52a2da1117175bc4bacd93c130966a1",
"ripemd160": "0x59384617f8a06efd57ab106c9e0c20c3e64137ac000000000000000000000000",
"sha256": "0xf9aeea729ff39f8d372d8552bca81eb2a3c5d433dc8f98140040a03b7d81ac92",
"values": [
"0xcdffcb5242e6",
"0xc1e101b60ebe4688",
"0x5819f0ef5537796e43bdcd48309f717d6f7ccffa",
"0xec3f3f9f",
false,
true
],
"types": [
"int184",
"int176",
"address",
"int64",
"bool",
"bool"
]
}
启用和禁用EIP-155的序列化已签名和未签名交易
{
"name": "random-998",
"privateKey": "0xd16c8076a15f7fb583f05dc12686fe526bc59d298f1eb7b9a237b458133d1dec",
"signedTransactionChainId5": "0xf8708391d450848517cfba8736fcf36da03ee4949577303fd4e0acbe72c6c116acab5bf63f0b1e9c8365fdc7827dc82ea059891894eb180cb7c6c45a52f62d2103420d3ad0bc3ba518d0a25ed910842522a0155c0ea2aee2ea82e75843aab297420bad907d46809d046b13d692928f4d78aa",
"gasLimit": "0x36fcf36da03ee4",
"to": "0x9577303fd4e0acbe72c6c116acab5bf63f0b1e9c",
"data": "0x7dc8",
"accountAddress": "0x6d4a6aff30ca5ca4b8422eea0ebcb669c7d79859",
"unsignedTransaction": "0xed8391d450848517cfba8736fcf36da03ee4949577303fd4e0acbe72c6c116acab5bf63f0b1e9c8365fdc7827dc8",
"nonce": "0x91d450",
"gasPrice": "0x8517cfba",
"signedTransaction": "0xf8708391d450848517cfba8736fcf36da03ee4949577303fd4e0acbe72c6c116acab5bf63f0b1e9c8365fdc7827dc81ba05030832331e6be48c95e1569a1ca9505c495486f72d6009b3a30fadfa05d9686a05cd3116b416d2362da1e9b0ca7fb1856c4e591cc22e63b395bd881ce2d3735e6",
"unsignedTransactionChainId5": "0xf08391d450848517cfba8736fcf36da03ee4949577303fd4e0acbe72c6c116acab5bf63f0b1e9c8365fdc7827dc8058080",
"value": "0x65fdc7"
}
单位转换。
{
"name": "one-two-three-3",
"gwei_format": "-1234567890123456.789012345",
"ether_format": "-1234567.890123456789012345",
"gwei": "-1234567890123456.789012345",
"ether": "-1234567.890123456789012345",
"finney": "-1234567890.123456789012345",
"wei": "-1234567890123456789012345",
"finney_format": "-1234567890.123456789012345"
}
测试JSON密钥库格式。
{
"mnemonic": null,
"name": "secretstorage_password",
"type": "secret-storage",
"password": "foo",
"privateKey": "0xf03e581353c794928373fb0893bc731aefc4c4e234e643f3a46998b03cd4d7c5",
"hasAddress": true,
"json": "{\"address\":\"88a5c2d9919e46f883eb62f7b8dd9d0cc45bc290\",\"Crypto\":{\"cipher\":\"aes-128-ctr\",\"ciphertext\":\"10adcc8bcaf49474c6710460e0dc974331f71ee4c7baa7314b4a23d25fd6c406\",\"cipherparams\":{\"iv\":\"1dcdf13e49cea706994ed38804f6d171\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"bbfa53547e3e3bfcc9786a2cbef8504a5031d82734ecef02153e29daeed658fd\"},\"mac\":\"1cf53b5ae8d75f8c037b453e7c3c61b010225d916768a6b145adf5cf9cb3a703\"},\"id\":\"fb1280c0-d646-4e40-9550-7026b1be504a\",\"version\":3}\n",
"address": "0x88a5c2d9919e46f883eb62f7b8dd9d0cc45bc290"
}