Hardhat是一个编译、部署、测试和调试以太坊应用的开发环境。它可以帮助开发人员管理和自动化构建智能合约和dApps过程中固有的重复性任务,并围绕这一工作流程轻松引入更多功能。这意味着hardhat在最核心的地方是编译、运行和测试智能合约。

Hardhat内置了Hardhat网络,这是一个专为开发设计的本地以太坊网络。主要功能有Solidity调试,跟踪调用堆栈、console.log()和交易失败时的明确错误信息提示等。

在Hardhat中编写智能合约测试是使用JavaScript或TypeScript完成的。

使用Waffle的测试是用Mocha和Chai一起编写的。

Mocha是流行的JavaScript测试框架之一,通过它添加和运行测试,从而保证代码质量。

```

const { expect } = require("chai");

describe("Greeter", function() {
  it("Should return the new greeting once it's changed", async function() {
    const Greeter = await ethers.getContractFactory("Greeter");
    const greeter = await Greeter.deploy("Hello, world!");
    
    await greeter.deployed();
    expect(await greeter.greet()).to.equal("Hello, world!");

    await greeter.setGreeting("Hola, mundo!");
    expect(await greeter.greet()).to.equal("Hola, mundo!");
  });
});

```

在终端上运行npx hardhat test, 你应该看到以下输出:

```

$ npx hardhat test

  Contract: Greeter
    ✓ Should return the new greeting once it's changed (762ms)

  1 passing (762ms)
  
```

这意味着测试通过了。 现在我们来解释一下每一行代码:


```

const { expect } = require("chai");

```

我们需要的是 Chai,它是一个断言库。 这些断言函数被称为 匹配器,我们在这里使用的这些函数其实来自Waffle。

这就是为什么我们要使用hardhat-waffle插件的原因,这使得我们更容易从以太坊中断言值。

```

describe("Greeter", function () {
  it("Should return the new greeting once it's changed", async function () {
    // ...
  });
});

```

这个包装器只是遵循Mocha提出的测试结构,但你可能已经注意到在it的回调函数中使用了async。 与以太坊网络和智能合约的交互是异步操作,因此大多数API和库都使用JavaScript的Promise来返回值。 使用 async可以让我们通过 await等待对合约和Hardhat网络节点的调用。

```

const Greeter = await ethers.getContractFactory("Greeter");

```

ethers.js中的ContractFactory是一个用于部署新的智能合约的抽象,所以这里的Greeter是我们的greeter合约实例的工厂。

```

const greeter = await Greeter.deploy("Hello, world!");

```

在 ContractFactory上调用 deploy()将开始部署,并返回一个解析为 Contract的 Promise。 这是一个合约对象,在这个对象上可以条用每个智能合约函数。 这里我们要把字符串 Hello, world!传递给合约的构造函数。

一旦合约部署完毕,就可以在greeter上调用合约方法,用它们来获取合约的状态。

```

expect(await greeter.greet()).to.equal("Hello, world!");

```

在这里,我们使用Contract实例来调用Solidity代码中的智能合约函数。 greet()返回迎接者的问候语,我们正在检查它是否等于Hello, world!,因为它应该相等。 这里,我们使用了Chai匹配器expect、to和equal。

```

await greeter.setGreeting("Hola, mundo!");
expect(await greeter.greet()).to.equal("Hola, mundo!");

```

我们可以用相同的方式修改合约的状态, 调用 setGreeting将设置一个新的问候信息。 在解析了 Promise之后,我们再进行一次断言,以验证问候语是否真正改变了。

05-13 01:56