diff --git a/components/learn/modules/ROOT/pages/writing-automated-tests.adoc b/components/learn/modules/ROOT/pages/writing-automated-tests.adoc index 75078448..204e6a40 100644 --- a/components/learn/modules/ROOT/pages/writing-automated-tests.adoc +++ b/components/learn/modules/ROOT/pages/writing-automated-tests.adoc @@ -1,99 +1,99 @@ -= Writing Automated Smart Contract Tests += 编写智能合约自动化测试 -In a blockchain environment, a single mistake could cost you all of your funds - or even worse, your users' funds! This guide will help you develop robust applications by writing automated tests that verify your application behaves exactly as you intended. +在区块链环境中,一个错误可能花费掉你所有的资金——甚至更糟,它会花费掉你用户的资金!这个指南将会帮助你开发健壮的应用程序,通过编写自动化测试来检测应用是不是像你预期的那样运行。 -We'll cover the following topics: +我们接下来将会讨论以下话题: - * <> - * <> - * <> + * <> + * <> + * <> -=== About Testing +=== 关于测试 -There is a a wide range of testing techniques, from xref:deploying-and-interacting.adoc#interacting-from-the-command-line[simple manual verifications] to complex end-to-end setups, all of them useful in their own way. +测试技术有很多种,从 xref:deploying-and-interacting.adoc#interacting-from-the-command-line[简单的手动验证] 到复杂的端到端设置,每种方式都有它们的用处。 -When it comes to smart contract development though, practice has shown that contract https://en.wikipedia.org/wiki/Unit_testing[_unit testing_] is exceptionally worthwhile. These tests are simple to write and quick to run, and let you add features and fix bugs in your code with confidence. +当涉及到智能合约开发时,经验表明对合约的 https://en.wikipedia.org/wiki/Unit_testing[_单元测试_] 是值得期待的。这些测试都很容易编写,并且运行很快,同时你可以很容易地给代码增加特征或是修改漏洞。 -Smart contract unit testing consists of multiple small, focused tests, which each check a small part of your contract for correctness. They can often be expressed in single sentences that make up a specification, such as 'the admin is able to pause the contract', 'transferring tokens emits an event' or 'non-admins cannot mint new tokens'. +智能合约单元测试包括多种小规模的针对性测试,它们可以检查合约中每一个小部分的正确性。可以使用单独的句子将测试规范表达出来,例如“管理员可以暂停合约”,“转移代币会触发事件”或者“非管理员不能挖矿获得新币”。 [[setting-up-a-testing-environment]] -== Setting up a Testing Environment +== 配置测试环境 -You may be wondering _how_ we're going to run these tests, since smart contracts are executed inside a blockchain. Using the actual Ethereum network would be very expensive, and while testnets are free, they are also slow (with blocktimes between 5 and 20 seconds). If we intend to run hundreds of tests whenever we make a change to our code, we need something better. +因为智能合约必须要在区块链上执行,所以你也许想知道我们将要 _怎样_ 运行这些测试用例。使用实际的以太坊网络费用很高,测试网络是免费的,但它很慢(出块时间在5到20秒之间)。如果我们想要在每一次修改代码后运行成百上千个测试用例,那么我们还需要找到更适合的测试网络。 -What we will use is called a _local blockchain_: a slimmed down version of the real thing, disconnected from the Internet, running on your machine. This will simplify things quite a bit: you won't need to get Ether, and new blocks will be mined instantly. +我们将要使用的就是 _本地区块链_ :它是一个以太坊真实版本的精简版,运行在你的电脑上,并且没有与互联网连接。这将简化很多事情:你不需要获取以太币,也能很快挖出新块。 -To aid us in this we'll use the xref:test-environment::index.adoc[*OpenZeppelin Test Environment*], a JavaScript library that will take care of setting up our local blockchain. +为了帮助我们测试,我们将会使用 xref:test-environment::index.adoc[*OpenZeppelin测试环境*],它是一个JavaScript库,可以帮助我们设置本地区块链。 -NOTE: If you've read the xref:deploying-and-interacting.adoc#local-blockchain[Deploying and Interacting] guide, you will already be familiar with https://github.com/trufflesuite/ganache-cli/[Ganache]. This is what Test Environment uses under the hood, taking care of its configuration for you. +NOTE: 如果你已经阅读了 xref:deploying-and-interacting.adoc#local-blockchain[部署和交互],你应该已经熟悉了 https://github.com/trufflesuite/ganache-cli/[Ganache]。这就是测试环境在底层的用处,它可以帮助你管理配置。 -To install the OpenZeppelin Test Environment, run: +下载OpenZeppelin测试环境,运行以下命令: ```console $ npm install --save-dev @openzeppelin/test-environment ``` -Once you `require` the library from your JavaScript code, it will automatically run a local testing blockchain for you. It also exports a list of accounts that have been pre-funded with Ether and convenient ways to load your contracts from their compiled artifacts, among other utilities. +一旦你 `require` 了自己的JavaScript代码库,它将会自动运行一个本地测试链。它将会输出一个账户列表,列表中的账户都预先充值了Ether。还会列出通过编译后的文件和通过其他帮助工具(函数)来加载合约的简便方法。 ```javascript const { accounts, contract } = require('@openzeppelin/test-environment'); -// Use the different accounts, which are unlocked and funded with Ether +// 使用不同解锁且有资产的账户 const [ admin, deployer, user ] = accounts; -// Create a contract object from a compilation artifact +// 使用artifact创建一个合约对象 const MyContract = contract.fromArtifact('MyContract'); ``` -For detailed information on these exported values and their usage, refer to Test Environment's xref:test-environment::api.adoc[API reference]. +如果你想要更加详细的了解输出的值和它们的用处,那么可以查看测试环境的 xref:test-environment::api.adoc[API参考]. [[writing-unit-tests]] -== Writing Unit Tests +== 编写单元测试 -In order to actually run your tests, you will need to also install a JavaScript _test runner_. You are free to use any of the xref:test-environment::choosing-a-test-runner.adoc[recommended ones]: for this guide, we'll pick https://mochajs.org/[Mocha] with https://www.chaijs.com/[Chai] assertions. +为了实际运行你的测试实例,你需要下载JavaScript的 _test runner_。你可以使用 xref:test-environment::choosing-a-test-runner.adoc[推荐列表] 中的任何一个:在本指南中,我们将选择 https://mochajs.org/[Mocha] 和 https://www.chaijs.com/[Chai]。 ```console $ npm install --save-dev mocha chai ``` -Create a `test` directory: this is where you will keep your test files. These are best structured by mirroring xref:developing-smart-contracts.adoc#setting-up-a-solidity-project[the `contracts` directory]: for each `.sol` file there, create a corresponding `.test.js` file. +新建一个 `test` 目录:用来存放你的测试文件。最好的构建这些文件的方法就是通过镜像 xref:developing-smart-contracts.adoc#setting-up-a-solidity-project[`contracts`目录]:对 `contracts` 目录中的每一个 `.sol` 文件,都创建一个对应的 `.test.js` 文件。 -Time to write our first tests! These will test properties of the `Box` contract xref:developing-smart-contracts.adoc#box-contract[from previous guides]: a simple contract that lets you `retrieve` a value the owner previously `store` d. +现在到了编写我们第一个测试的时候了!我们将会测试 xref:developing-smart-contracts.adoc#box-contract[前面指南中出现的] `Box` 合约的属性:这个合约使你可以 `获取` 合约所有者预先 `存储` 在变量中的值。 ```javascript // test/Box.test.js -// Load dependencies +// 加载依赖 const { accounts, contract } = require('@openzeppelin/test-environment'); const { expect } = require('chai'); -// Load compiled artifacts +// 加载已编译的artifacts const Box = contract.fromArtifact('Box'); -// Start test block +// 开始测试模块 describe('Box', function () { const [ owner ] = accounts; beforeEach(async function () { - // Deploy a new Box contract for each test + // 为每个测试部署一个新的Box合约 this.contract = await Box.new({ from: owner }); }); - // Test case + // 测试用例 it('retrieve returns a value previously stored', async function () { - // Store a value - recall that only the owner account can do this! + // 存储一个值——记得只有所有者账户才能执行此操作! await this.contract.store(42, { from: owner }); - // Test if the returned value is the same one - // Note that we need to use strings to compare the 256 bit integers + // 如果返回值是相同的就进行测试 + // 注意我们需要使用字符串的格式与256位int类型做比较 expect((await this.contract.retrieve()).toString()).to.equal('42'); }); }); ``` -TIP: Many books have been written about how to structure unit tests: for a quick reference, check out the https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/test[tests for OpenZeppelin Contracts], or the following https://medium.com/coinmonks/how-to-test-ethereum-smart-contracts-ac28fa852281[guide for ERC20 tests]. +TIP: 很多书籍都写过如何将单元测试结构化:想要获取此类参考,可以查看 https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/test[OpenZeppelin合约的测试],或者接下来的 https://medium.com/coinmonks/how-to-test-ethereum-smart-contracts-ac28fa852281[ERC20测试指南]. -We are now ready to run our tests! The best way to do this is by adding a `test` script to your `package.json`: +现在我们准备好运行测试了!最好的方式就是给 `package.json` 添加一个 `test` 脚本: [source,diff] ---- @@ -102,7 +102,7 @@ We are now ready to run our tests! The best way to do this is by adding a `test` } ---- -With this, running `npm test` will execute all tests in the `test` directory, checking that your contracts work the way you meant them to: +有了这个脚本,运行 `npm test` 命令就可以执行 `test` 目录下所有的测试了,这样就可以检查合约是否按照我们希望的那样运行: ```console $ npm test @@ -112,25 +112,25 @@ $ npm test [TIP] ==== -Don't forget to re-compile your contracts if you make changes to them! If you want to do this automatically on each test run, set your `test` script instead to: +如果你修改了合约,别忘了要重新编译!如果你希望在每个测试之前自动重新编译,那么可以将 `test` 脚本设置为: `oz compile && mocha --exit --recursive test` ==== -Test Environment comes with sensible defaults that should work for most use-cases, but you can always xref:test-environment::getting-started.adoc#configuration[configure] it to provide more accounts or use different kinds of contract objects, among others. +测试环境的默认值是可以修改的,默认的参数适用于大多数场景,但是你也可以 xref:test-environment::getting-started.adoc#configuration[设置] 参数来让它提供更多的账户,或者使用不同种类的合约对象。 -It's also a very good idea at this point to set up a Continuous Integration service such as https://circleci.com/[CircleCI] to make your tests run automatically every time you commit your code to GitHub. +同时,也可以设置持续集成服务,例如 https://circleci.com/[CircleCI]。这样可以在你每次提交代码到GitHub后自动运行测试。 [[performing-complex-assertions]] -== Performing Complex Assertions +== 执行复杂命令 -Many interesting properties of your contracts may be hard to capture, such as: +合约中很多有趣的属性很难获取到,例如: - * verifying that the contract reverts on errors - * measuring by how much an account's Ether balance changed - * checking that the proper events are emitted + * 验证合约是否因错误导致回滚 + * 判断一个账户的以太币余额变化了多少 + * 检查是否触发了正确的事件 -xref:test-helpers::index.adoc[*OpenZeppelin Test Helpers*] is a library designed to help you test all of these properties. It will also simplify the tasks of simulating time passing on the blockchain and handling very large numbers. +xref:test-helpers::index.adoc[*OpenZeppelin 测试助手*] 是一个可以帮助你测试这些属性的库。它将会简化在区块链上模拟时间的任务,同时它也可以处理大量任务。 ```console $ npm install --save-dev @openzeppelin/test-helpers @@ -142,7 +142,7 @@ $ npm install --save-dev @openzeppelin/test-helpers const { accounts, contract } = require('@openzeppelin/test-environment'); const { expect } = require('chai'); -// Import utilities from Test Helpers +// 从测试帮助导入实体 const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); const Box = contract.fromArtifact('Box'); @@ -150,7 +150,7 @@ const Box = contract.fromArtifact('Box'); describe('Box', function () { const [ owner, other ] = accounts; - // Use large integers ('big numbers') + // 使用大整数 ('big numbers') const value = new BN('42'); beforeEach(async function () { @@ -160,19 +160,19 @@ describe('Box', function () { it('retrieve returns a value previously stored', async function () { await this.contract.store(value, { from: owner }); - // Use large integer comparisons + // 使用大整数比较 expect(await this.contract.retrieve()).to.be.bignumber.equal(value); }); it('store emits an event', async function () { const receipt = await this.contract.store(value, { from: owner }); - // Test that a ValueChanged event was emitted with the new value + // 测试新的值将会触发一个ValueChanged事件 expectEvent(receipt, 'ValueChanged', { newValue: value }); }); it('non owner cannot store a value', async function () { - // Test a transaction reverts + // 测试交易回滚 await expectRevert( this.contract.store(value, { from: other }), 'Ownable: caller is not the owner' @@ -181,11 +181,11 @@ describe('Box', function () { }); ``` -No configuration is required: Test Environment will detect the Test Helpers and do the hard work for you. +不需要任何配置:测试环境将会发现测试助手然后帮助你完成复杂的工作。 -These will test properties of the `Box` contract xref:developing-smart-contracts.adoc#using-openzeppelin-contracts[from previous guides]: a simple contract that lets you `retrieve` a value the owner previously `store`d. +这些将测试 xref:developing-smart-contracts.adoc#using-openzeppelin-contracts[先前的指南中的] `Box` 合约的属性:这是一个简单的合约,可以 `检索` 所有者先前 `存储` 的值。 -Run your tests again to see the Test Helpers in action: +再次运行你的测试就可以看到测试助手正在运行: ```console $ npm test @@ -195,14 +195,14 @@ $ npm test ✓ non owner cannot store a value ``` -The Test Helpers will let you write powerful assertions without having to worry about the low-level details of the underlying Ethereum libraries. To learn more about what you can do with them, head to their xref:test-helpers::api.adoc[API reference]. +测试助手将会帮助你编写有效的命令,这样你就不用担心以太坊库中的底层细节。想要知道它还有什么用处,可以查看它的 xref:test-helpers::api.adoc[API参考]。 -TIP: The OpenZeppelin Test Environment is not required to use the Test Helpers: to learn how to use them standalone or integrated in other systems, refer to their xref:test-helpers::configuration.adoc[documentation]. +TIP: 使用测试助手不需要OpenZeppelin测试环境:要了解如何独立使用它们或将其集成到其他系统中,可以参考 xref:test-helpers::configuration.adoc[文档]。 -== Next Steps +== 下一步 -Once you have thoroughly tested your contracts and are reasonably sure of their correctness, you'll want to deploy them to a real network and start interacting with them. The following guides will get you up to speed on these topics: +一旦对合约进行了全面的测试并确定了合约的正确性,接下来就需要将其部署到真实的网络并开始与它们进行交互。以下指南可帮助你快速掌握这些问题: - * xref:connecting-to-public-test-networks.adoc[Connecting to Public Test Networks] - * xref:deploying-and-interacting.adoc[Deploying and Interacting] - * xref:preparing-for-mainnet.adoc[Preparing for Mainnet] + * xref:connecting-to-public-test-networks.adoc[连接到公共测试网络] + * xref:deploying-and-interacting.adoc[开发和交互] + * xref:preparing-for-mainnet.adoc[准备主网]