# harthat插件

By [Cognitive](https://paragraph.com/@cognitive) · 2022-09-12

---

编写单元测试首先需要我们在测试钩子中编写发布合约的代码，这意味着，我们需要在每次 `beforeEach` 钩子中重新发布我们的合约并使其从零状态开始运行。

即使 hardhat 支持在内存中运行区块链并整合了单元测试流程，但这样反复的发布合约也会极大拖慢测试速度。

因此，就单元测试的最佳实践，我向大家推荐 `hardhat-deploy` 插件。

`hardhat-deploy` 插件支持使用 `evm_snapshot` 快速地跳转到某个高度的区块链状态，因此，我们可以使用它在单元测试中维护测试前、中、后以及各种特定高度状态，极大地加快测试速度。

[https://github.com/wighawag/hardhat-deploy](https://github.com/wighawag/hardhat-deploy)

> 注意，引入 `hardhat-deploy` 插件，需要修改对应的 `@nomiclabs/hardhat-ethers` 插件来源，这可能会导致在未来的 `npm install` 中带来版本冲突，如果你遇到了版本冲突，可以使用 `npm install --force` 跳过版本依赖检查，强制安装两者。

    "devDependencies": {
        "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
        "hardhat-deploy": "^0.11.2",
        ...
    }
    

简单来说，在单元测试中，我们可以使用：

    await deployments.fixture(['SomeContractName']);
    

来确保在测试执行前跳回某个状态。如果你需要更加复杂和自定义的 fixture（而非直接跳回某个合约发布后的干净状态）可以使用 `deployments.createFixture` 来创建自定义 fixture，具体的范例代码和指南可以在这里寻找到：

[https://github.com/CodeforDAO/contracts/blob/main/utils/helpers.js#L42](https://github.com/CodeforDAO/contracts/blob/main/utils/helpers.js#L42)

[https://github.com/wighawag/hardhat-deploy#creating-fixtures](https://github.com/wighawag/hardhat-deploy#creating-fixtures)

值得注意的是，使用 `hardhat-deploy` 插件会同时改变我们发布合约的代码逻辑（正如其名）它支持在 `./deploy` 文件夹下编写每个合约的发布脚本。事实上，默认的 `deployments.fixture` 正会退回这些发布脚本所叙述的合约状态。

不同于 hardhat 默认的发布脚本（使用 `npx hardhat run`）我们可以使用 `hardhat-deploy` 插件提供的功能在发布脚本中做更多工作，例如使用 `execute` 函数立即修改发布后的合约状态，这会在对权限敏感的合约当中非常有用：

    const { deploy, execute } = deployments;
    const shareGovernor = await deploy('ShareGovernor', {
        contract: 'TreasuryGovernor',
        from: deployer,
        args: [name + '-ShareGovernor', share.address, treasury.address, settings.share.governor],
        log: true,
      });
    
      // Setup governor roles
      // Both membership and share governance have PROPOSER_ROLE by default
      await execute(
        'Treasury',
        { from: deployer },
        'grantRole',
        PROPOSER_ROLE,
        membershipGovernor.address
      );
    

除此之外，`hardhat-deploy` 插件还提供了非常多的 HRE 实用函数，例如`getNamedAccounts` 能帮助我们命名本地测试账户，而非使用数组下标访问它们。你可以参考该插件的 GitHub 主页了解这些实用功能。

测试覆盖率与gas报告
-----------

当合约的单元测试编码到一定程度之后，我们会希望这些合约被发布到某个测试或生产环境（例如测试网络或 ETH 主网）时是否是健壮和低成本的，在此时，我向你推荐两个 hardhat 插件 `hardhat-gas-reporter` 与 `solidity-coverage`

![hardhat-gas-reporter
](https://storage.googleapis.com/papyrus_images/196d736c2f23e8448e0d03faca964e8747fa45a92d467c34e2a6787c29bfeac2.png)

hardhat-gas-reporter

`hardhat-gas-reporter` 插件帮助你了解运行单元测试中部署和执行合约方法消耗的 gas 费用，如果在本地环境变量中提供 `COINMARKETCAP_API_KEY`，它会自动将这些成本折算为美元或其他法币计价。

[https://github.com/cgewecke/hardhat-gas-reporter](https://github.com/cgewecke/hardhat-gas-reporter)

`solidity-coverage` 插件提供单元测试覆盖率报告，这有助于开发团队理解合约是否得到了应有的测试。

[https://github.com/sc-forks/solidity-coverage](https://github.com/sc-forks/solidity-coverage)

### 其他插件

如前所述，hardhat 并不需要以来太多的插件就可以正常工作，满足大部分合约开发团队的需求，我在这里推荐两个其他的使用插件，他们是 `@nomiclabs/hardhat-etherscan` 和 `@tenderly/hardhat-tenderly`

这些插件都是可选的，并依赖第三方服务的 API Key，各位读者可以根据自己的情况选择是否使用他们。

`hardhat-etherscan` 插件将 etherscan 网站的源码 verify 功能整合到发布工作流中，能够将所发布合约的源码和 ABI 都展示在合约地址页面。

[https://github.com/NomicFoundation/hardhat](https://github.com/NomicFoundation/hardhat)

`hardhat-tenderly` 插件整合了 Tenderly 工作流，后者是一个新兴的 CI/监控 平台，能够帮助我们监控线上合约的状态并提供 debug 建议。

[https://tenderly.co/](https://tenderly.co/)

[https://github.com/Tenderly/hardhat-tenderly](https://github.com/Tenderly/hardhat-tenderly)

---

*Originally published on [Cognitive](https://paragraph.com/@cognitive/harthat)*
