Writing Tests Examples
This page demonstrates how to write test for FunC contracts created in with Blueprint SDK (Sandbox).
Test suites built for demo contract fireworks. The fireworks is a smart contract which initially run via set_first
message.
Once a new FunC project is created via npm create ton@latest
, a test file tests/contract.spec.ts
will be autogenerated in the project directory for testing the contract:
import ...
describe('Fireworks', () => {
...
expect(deployResult.transactions).toHaveTransaction({
...
});
});
it('should deploy', async () => {
// the check is done inside beforeEach
// blockchain and fireworks are ready to use
});
Running tests using the following command:
npx blueprint test
Additional options and vmLogs may be specified with blockchain.verbosity
:
blockchain.verbosity = {
...blockchain.verbosity,
blockchainLogs: true,
vmLogs: 'vm_logs_full',
debugLogs: true,
print: false,
}
Direct Unit Tests
Fireworks demonstrate different operating with sending messages in the TON Blockchain.
Once you deploy this with message set_first
with enough TON amount, it will be automatically executed with primary and usable combinations of send modes.
Fireworks redeployed itself, as result it will be created 3 entities of Fireworks entities, while each of entity has own ID(keep it in storage) and, as a result, different Smart Contract Address.
For clearness define different by ID Fireworks instances (different state_init
) with the following names:
- 1 - Fireworks setter - The entity that spread different launch op codes. Could be extended up to four different opcodes.
- 2 - Fireworks launcher-1 - The Fireworks instance, which launch first fireworks, means messages will be sent to the launcher.
- 3 - Fireworks launcher-2 - The Fireworks instance, which launch second fireworks, means messages will be sent launcher.
Expand details on transactions
index - is an ID of a transaction in the launchResult
array.
0
- External request to the treasury (the Launcher) that resulted with a outbound messageop::set_first
with 2.5 to fireworks1
- The transaction in Fireworks setter contract invoked withop::set_first
and executed with two outbound messages to the Fireworks Launcher-1 and Fireworks Launcher-22
- The transaction in the Fireworks launcher 1 invoked withop::launch_first
, and executed with four outbound messages to the Launcher.3
- The transaction in the Fireworks launcher 2 invoked withop::launch_second
, and executed with a outbound message to the Launcher.4
- Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent withsend mode = 0
.5
- Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent withsend mode = 1
6
- Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent withsend mode = 2
7
- Transaction in the Launcher with incoming message from the Fireworks launcher 1. This message sent withsend mode = 128 + 32
8
- Transaction in the Launcher with incoming message from the Fireworks launcher 2. This message sent withsend mode = 64
Each 'firework' - is outbound message with a unique message body appears in transactions with ID:3 and ID:4.
Bellow the list of test for each transaction expected successfully executed. Transaction[ID:0] External request to the treasury (the Launcher) that resulted with a outbound message op::set_first
with 2.5 to fireworks. In case you will deploy Fireworks to the blockchain launcher is your wallet.
Transaction ID:1 Success Test
This test checks if the fireworks are successfully set by sending a transaction with a value of 2.5 TON. This is the simplest case, the main purpose here to assert result of transaction success property to true.
To filter certain transaction from the launhcResult.transactions
array, we can use the most convince fields.
With
from
(contract sender address), to
(contract destination address), op
(Op code value) - we will retrieve only one transaction for this combination.
The transaction[ID:1] in Fireworks Setter contract invoked with op::set_first
and executed with two outbound messages to the Fireworks launcher-1 and 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
})
});
Transaction ID:2 Success Test
This test checks if the transaction[ID:2] executed successfully.
The transaction in the Fireworks launcher 1 invoked with op::launch_first
, and executed with four outbound messages to 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);
});
In cases, when transaction should affect the state of contract, it is possible to specify this with destroyed
, endStatus
fields.
The full list of Account Status related fields:
destroyed
-true
- if the existing contract was destroyed due to executing a certain transaction. Otherwise -false
.deploy
- Custom Sandbox flag that indicates whether the contract was deployed during this transaction.true
if contract before this transaction was not initialized and after this transaction became initialized. Otherwise -false
.oldStatus
- AccountStatus before transaction execution. Values:'uninitialized'
,'frozen'
,'active'
,'non-existing'
.endStatus
- AccountStatus after transaction execution. Values:'uninitialized'
,'frozen'
,'active'
,'non-existing'
.
Transaction ID:3 Success Test
This test checks if the transaction[ID:3] executed successfully.
The transaction[ID:3] carries out in the Fireworks launcher 1, invokes with op::launch_first
, and executes with four outbound messages to 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);
});