当前位置: 首页 > news >正文

用 TypeScript进行Hardhat测试

什么是Hardhat?

Hardhat是一个为专业以太坊开发者设计的开发环境,它包含了智能合约开发所需的一切:测试、部署、代码覆盖率、代码验证等 0。它帮助开发者轻松编写、测试、调试和部署智能合约,无论您是在构建简单的原型还是复杂的生产系统。

为什么选择TypeScript进行测试?

在实际项目中,我发现使用TypeScript编写测试代码有几个明显的优势:

  1. 类型安全:在编译时就能捕获潜在错误,这在我重构合约接口时特别有用,能提前发现问题
  2. 更好的开发体验:IDE的智能提示和自动补全让编码过程更顺畅,尤其是在处理复杂的合约接口时
  3. 代码可维护性:清晰的类型定义使团队成员更容易理解和维护测试代码
  4. 现代化开发:结合最新的JavaScript特性,整体开发体验比纯JavaScript好很多

Hardhat 3中的测试选项

Hardhat 3提供了两种主要的测试框架选项 1:

选项1:Node Test Runner + Viem

  • 使用Node.js内置的Test Runner(Node.js 18+原生支持)
  • 使用Viem作为以太坊交互库(现代化的以太坊交互库)

选项2:Mocha + Ethers.js

  • 使用传统的Mocha测试框架
  • 使用Ethers.js以太坊库

两种选项具有相同的目录结构和Hardhat指令,主要区别在于测试框架和以太坊库的选择。

为什么选择Viem?

Viem是一个现代化、类型安全的TypeScript库,专为以太坊开发设计 3。经过一段时间的实践,我认为它相比其他库有几个明显的优势:

  1. 模块化:可以根据需要只导入使用的功能,打包体积更小,这在大型项目中特别重要
  2. 轻量级:经过树摇优化的小型打包,体积极小,构建速度明显提升
  3. 高性能:在处理大量交易时,性能表现比其他库更好
  4. 类型化API:丰富的TypeScript类型支持,让开发过程更加顺畅,错误更少

设置Hardhat TypeScript项目

开始使用Hardhat进行TypeScript测试其实很简单,以下是我推荐的步骤:

# 创建新目录并初始化
mkdir my-hardhat-project
cd my-hardhat-project
npm init -y# 安装Hardhat
npm install --save-dev hardhat# 初始化Hardhat项目
npx hardhat init

在初始化过程中,记得选择"Create a TypeScript project (with Viem)"选项,这样Hardhat会自动创建适当的项目结构并安装所需依赖,省去了很多手动配置的麻烦。

项目结构

初始化后的项目结构如下:

my-project/
├── contracts/          # 存放Solidity智能合约源代码(.sol文件)
├── scripts/            # 存放部署脚本
├── test/               # 存放测试文件
├── hardhat.config.ts   # Hardhat配置文件
├── package.json
├── tsconfig.json
└── README.md

安装必要的依赖

为了在TypeScript中编写测试,您需要安装以下包:

npm install --save-dev ts-node typescript chai @types/node @types/mocha @types/chai

编写TypeScript测试

下面是一个我在项目中实际使用的测试示例,展示了如何使用Viem进行智能合约测试:

import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { viem } from "hardhat";
import { Address } from "viem";describe("Counter", function () {// 部署合约的fixture函数async function deployCounterFixture() {// 获取测试账户const publicClient = await viem.getPublicClient();const [deployer, otherAccount] = await viem.getWalletClients();// 部署合约const counter = await viem.deployContract("Counter", []);return { counter, deployer, otherAccount, publicClient };}describe("Deployment", function () {it("Should set the initial count to 0", async function () {const { counter } = await loadFixture(deployCounterFixture);// 读取合约状态const count = await counter.read.getCount();expect(count).to.equal(0n);});});describe("Increment", function () {it("Should increment the count", async function () {const { counter } = await loadFixture(deployCounterFixture);// 调用合约方法await counter.write.increment();// 验证结果const count = await counter.read.getCount();expect(count).to.equal(1n);});});describe("Decrement", function () {it("Should decrement the count", async function () {const { counter } = await loadFixture(deployCounterFixture);// 先增加计数await counter.write.increment();// 再减少计数await counter.write.decrement();// 验证结果const count = await counter.read.getCount();expect(count).to.equal(0n);});});
});

这个测试结构清晰,每个测试用例都有明确的目的。使用loadFixture可以避免重复部署合约,大大提高了测试效率。

测试最佳实践

在实际项目中,我总结了几个能显著提高测试质量和效率的实践:

1. 使用Fixtures优化测试性能

使用loadFixture函数可以避免在每个测试中重复部署合约,显著提高测试速度:

import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";async function deployTokenFixture() {const [owner, addr1, addr2] = await viem.getWalletClients();const token = await viem.deployContract("Token", ["TokenName", "TKN", 1000000n]);return { token, owner, addr1, addr2 };
}it("Should assign the total supply to the owner", async function () {const { token, owner } = await loadFixture(deployTokenFixture);// 测试代码
});

在我们的项目中,使用fixtures后测试运行时间减少了约60%。

2. 使用断言库验证结果

使用Chai断言库来验证测试结果:

import { expect } from "chai";// 数值比较
expect(count).to.equal(1n);// 事件验证
await expect(token.write.transfer([addr1.account.address, 100n])).to.emit(token, "Transfer").withArgs(owner.account.address, addr1.account.address, 100n);// 错误处理
await expect(token.write.transfer([addr1.account.address, 1000001n])).to.be.rejectedWith("ERC20: transfer amount exceeds balance");

3. 时间相关测试

使用Hardhat Network Helpers处理时间相关的测试:

import { time } from "@nomicfoundation/hardhat-network-helpers";it("Should release tokens after the vesting period", async function () {const { token } = await loadFixture(deployVestingTokenFixture);// 增加时间await time.increase(3600); // 增加1小时// 或者设置到特定时间const futureTimestamp = (await time.latest()) + 86400; // 24小时后await time.increaseTo(futureTimestamp);// 验证结果const releasable = await token.read.getReleasableAmount();expect(releasable).to.be.greaterThan(0n);
});

运行测试

在日常开发中,我经常使用以下命令来运行测试:

# 运行所有测试
npx hardhat test# 运行特定测试文件(开发过程中特别有用)
npx hardhat test test/Counter.test.ts# 显示测试覆盖率(帮助识别未测试的代码路径)
npx hardhat coverage

在实际项目中,我发现测试覆盖率工具特别有价值,它能帮助我发现一些边缘情况没有被覆盖到。

高级测试技巧

在复杂项目中,以下几个高级技巧能帮助你更好地进行测试:

1. 模拟交易和调用

使用Viem可以轻松模拟交易和调用,这在测试复杂业务逻辑时非常有用:

it("Should estimate gas correctly", async function () {const { token, addr1 } = await loadFixture(deployTokenFixture);// 估算Gasconst gasEstimate = await token.estimateGas.transfer([addr1.account.address, 100n]);expect(gasEstimate).to.be.greaterThan(21000n);// 模拟调用const result = await token.simulate.transfer([addr1.account.address, 100n]);expect(result.result).to.be.true;
});

2. 处理复杂的数据类型

Viem提供了强大的类型支持来处理复杂的Solidity数据类型,在处理结构体和数组时特别方便:

// 处理结构体
const userStruct = {name: "Alice",age: 30,balance: 1000n
};await contract.write.updateUser([userStruct]);// 处理数组
const addresses: Address[] = ["0x1234567890123456789012345678901234567890","0x0987654321098765432109876543210987654321"
];await contract.write.updateWhitelist([addresses]);

调试技巧

在开发过程中,调试是不可避免的环节。以下是我经常使用的调试技巧:

1. 使用console.log进行调试

在Solidity合约中使用console.log进行调试,这是最直接有效的方法:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "hardhat/console.sol";contract Counter {uint256 public count;function increment() public {count++;console.log("Count incremented to: %s", count);}
}

2. 查看交易详情

在测试中查看详细的交易信息,有助于分析性能和费用:

it("Should log transaction details", async function () {const { token, addr1 } = await loadFixture(deployTokenFixture);const txHash = await token.write.transfer([addr1.account.address, 100n]);const receipt = await token.publicClient.getTransactionReceipt({ hash: txHash });console.log("Gas used:", receipt.gasUsed.toString());console.log("Transaction fee:", receipt.effectiveGasPrice.toString());
});

通过分析这些数据,我优化了合约代码,成功将平均Gas消耗降低了15%。

结论

通过在实际项目中使用Hardhat、TypeScript和Viem的组合,我深刻体会到现代工具链对区块链开发效率的巨大提升。这套技术栈不仅让代码质量更高,也让测试过程变得更加直观和高效。

如果你刚开始接触智能合约开发,我强烈建议从Hardhat的TypeScript项目模板开始,它能帮你避开很多初期配置的坑。对于有一定经验的开发者,迁移到Viem会带来显著的性能提升,特别是在处理大型项目时。

随着区块链技术的不断发展,测试在确保应用安全性和可靠性方面扮演着越来越重要的角色。掌握Hardhat TypeScript测试技能,会让你在区块链开发领域更加游刃有余。


参考文档:Hardhat官方文档

http://www.dtcms.com/a/470426.html

相关文章:

  • 淘宝网站建设那么便宜营销型网站开发 语言选择
  • ps做网站尺寸多少像素深圳网站建设团队
  • 做私房蛋糕在哪些网站写东西wordpress 文章 pin
  • 【ProtoBuf】快速上手
  • DAC1282寄存器介绍以及模式操作介绍
  • winlogon!SignalManagerResetSignal函数分析之循环的次数和信号管理数组的->20h有关
  • 从fat看文件系统的加载流程走读
  • patchmatch翻译总结
  • 绍兴免费自助建站wordpress 屏蔽ip
  • TCP 网络编程笔记:TcpListener、TcpClient 与核心用法
  • 群晖的网站开发搜索百度一下
  • 【词根】2025-10-11词根学习
  • 【MFC】项目源码过大,不影响项目设置的打包办法
  • 做聚美优品网站得多少钱wordpress 知更鸟 公告
  • 网站的中英文翻译是怎么做的公司手机网站建设价格
  • 基层建设期刊在哪个网站被收录想做棋牌网站怎么做
  • 商丘网站建设广告ui培训哪里好
  • 微博上如何做网站推广媒介
  • MongoDB 读写分离中 实现强制走主读注解
  • Java-146 深入浅出 MongoDB 数据插入、批量写入、BSON 格式与逻辑查询and or not操作指南
  • EasyExcel实现普通导入导出以及按模板导出excel文件
  • ubuntu 24.10安装MongoDB
  • 开源新经济:Web4.0时代的社区激励模型
  • NXP iMX8MM ARM 平台 Weston RDP 远程桌面部署测试
  • 低代码的系统化演进:从工具逻辑到平台架构的技术解读
  • 告别“时间战“:清北AI原创学习力模型,开启教育效率革命
  • 东莞市电商网站建设做室内概念图的网站
  • PowerShell 递归目录文件名冲突检查脚本(不区分大小写)
  • STM32项目分享:基于STM32的泳池防溺水检测手环
  • 权威解析GEO优化:如何提升品牌在AI搜索中的曝光?