编写测试示例
此页面展示了如何为在Blueprint SDK(Sandbox)中创建的FunC合约编写测试。
测试套件为演示合约fireworks构建。Fireworks是一个通过set_first
消息初始化运行的智能合约。
通过npm create ton@latest
创建一个新的FunC项目后,测试文件tests/contract.spec.ts
将自动生成在项目目录中,用于测试合约:
import ...
describe('Fireworks', () => {
...
expect(deployResult.transactions).toHaveTransaction({
...
});
});
it('should deploy', async () => {
// the check is done inside beforeEach
// blockchain and fireworks are ready to use
});
使用以下命令运行测试:
npx blueprint test
可以通过blockchain.verbosity
指定附加选项和vmLogs:
blockchain.verbosity = {
...blockchain.verbosity,
blockchainLogs: true,
vmLogs: 'vm_logs_full',
debugLogs: true,
print: false,
}
直接 cell 测试
Fireworks演示了在TON区块链中发送消息的不同操作。
一旦你有足够TON金额并通过set_first
消息部署它,它将使用主要和可用的发送模式组合自动执行。
Fireworks重新部署自己,结果将创建3个Fireworks实体,每个实体都有自己的ID(被保存在存储中),因此有不同的智能合约地址。
为了清晰起见,我们定义不同ID的Fireworks实例(不同的state_init
)并以下列名称命名:
- 1 - Fireworks setter - 传播不同启动操作码的实体。可以扩展到四种不同的操作码。
- 2 - Fireworks launcher-1 - 启动第一个firework的Fireworks实例,意味着消息将被发送 给launcher。
- 3 - Fireworks launcher-2 - 启动第二个firework的Fireworks实例,意味着消息将被发送给launcher。
展开交易细节
index - 是launchResult
数组中交易的ID。
0
- 对资金库(the Launcher)的外部请求,导致向fireworks发送2.5 TON的出站消息op::set_first
1
- 在Fireworks setter合约中使用op::set_first
调用的交易,并执行了两个出站消息到Fireworks Launcher-1和Fireworks Launcher-22
- 在Fireworks launcher 1中使用op::launch_first
调用的交易,并执行了四个出站消息到the Launcher。3
- 在Fireworks launcher 2中使用op::launch_second
调用的交易,并执行了一个出站消息到the Launcher。4
- 在the Launcher中来自Fireworks launcher 1的入站消息的交易。此消息以send mode = 0
发送。5
- 在the Launcher中来自Fireworks launcher 1的入站消息的交易。此消息以send mode = 1
发送。6
- 在the Launcher中来自Fireworks launcher 1的入站消息的交易。此消息以send mode = 2
发送。7
- 在the Launcher中来自Fireworks launcher 1的入站消息的交易。此消息以send mode = 128 + 32
发送。8
- 在the Launcher中来自Fireworks launcher 2的入站消息的交易。此消息以send mode = 64
发送。
每个“firework” - 是交易ID:3和ID:4中出现的带有独特消息体的出站消息。
以下是每个预期成功执行的交易的测试列表。交易[ID:0]是对资金库(the Launcher)的外部请求,导致向fireworks发送2.5 TON的出站消息op::set_first
。如果您将Fireworks部署到区块链,launcher会是您的钱包。
交易ID:1 成功测试
此测试检查是否通过发送2.5 TON的交易成功设置了fireworks。 这是最简单的情况,主要目的是确认交易成功属性为true。
要从launhcResult.transactions
数组中过滤出特定交易,我们可以使用最方便的字段。
通过from
(合约发送方地址)、to
(合约目的地地址)、op
(操作码值) - 我们将仅检索此组合的一个交易。
交易[ID:1]在Fireworks Setter合约中被op::set_first
调用,并执行了两个出站消息到Fireworks Launcher-1和Fireworks Launcher-2。
it('first transaction[ID:1] should set fireworks successfully', async () => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
expect(launchResult.transactions).toHaveTransaction({
from: launcher.address,
to: fireworks.address,
success: true,
op: Opcodes.set_first
})
});
交易ID:2 成功测试
此测试检查交易[ID:2]是否成功执行。
交易[ID:2]在Fireworks launcher 1中进行,用op::launch_first
调用,并执行了四个出站消息到the Launcher。
it('should exist a transaction[ID:2] which launch first fireworks successfully', async () => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
expect(launchResult.transactions).toHaveTransaction({
from: fireworks.address,
to: launched_f1.address,
success: true,
op: Opcodes.launch_first,
outMessagesCount: 4,
destroyed: true,
endStatus: "non-existing",
})
printTransactionFees(launchResult.transactions);
});
在交易要影响合约状态的情况下,可以使用destroyed
、endStatus
字段指定。
完整的账户状态相关字段列表:
destroyed
-true
- 如果现有合约因执行某个交易而被销毁。否则 -false
。deploy
- 自定义沙盒标志位,表明合约在此交易期间是否部署。如果合约在此交易前未初始化,而在此交易后变为已初始化,则为true
。否则 -false
。oldStatus
- 交易执行前的账户状态。值:'uninitialized'
,'frozen'
,'active'
,'non-existing'
。endStatus
- 交易执行后的账户状态。值:'uninitialized'
,'frozen'
,'active'
,'non-existing'
。
交易ID:3 成功测试
此测试检查交易[ID:3]是否成功 执行。
交易[ID:3]在Fireworks launcher 1中进行,用op::launch_first
调用,并执行了四个出站消息到the Launcher。
it('should exist a transaction[ID:3] which launch second fireworks successfully', async () => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(launcher.getSender(), toNano('2.5'));
expect(launchResult.transactions).toHaveTransaction({
from: fireworks.address,
to: launched_f2.address,
success: true,
op: Opcodes.launch_second,
outMessagesCount: 1
})
printTransactionFees(launchResult.transactions);
});
交易ID:4 成功测试
此测试检查交易[ID:4]是否成功执行。
收到来自Fireworks launcher 1的入站消息,交易[ID:4]在the Launcher(部署钱包)中进行。此消息以send mode = 0
发送。
it('should exist a transaction[ID:4] with a comment send mode = 0', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
toNano('2.5'),
);
expect(launchResult.transactions).toHaveTransaction({
from: launched_f1.address,
to: launcher.address,
success: true,
body: beginCell().storeUint(0,32).storeStringTail("send mode = 0").endCell() // 0x00000000 comment opcode and encoded comment
});
})
交易ID:5 成功测试
此测试检查交易[ID:5]是否成功执行。
收到来自Fireworks launcher 1的入站消息,交易[ID:5]在the Launcher中进行。此消息以send mode = 1
发送。
it('should exist a transaction[ID:5] with a comment send mode = 1', async() => {
const launcher = await blockchain.treasury('launcher');
const launchResult = await fireworks.sendDeployLaunch(
launcher.getSender(),
toNano('2.5'),
);
expect(launchResult.transactions).toHaveTransaction({
from: launched_f1.address,
to: launcher.address,
success: true,
body: beginCell().storeUint(0,32).storeStringTail("send mode = 1").endCell() // 0x00000000 comment opcode and encoded comment
});
})