Skip to main content

Testing

To wrap up this tutorial, we'll set up a simple automated test for our dapp contracts. We will be using jest, but any nodejs test runner works fine.

Here we'll only test the happy path for a transfer on our private token contract, but in a real application you should be testing both happy and unhappy paths, as well as both your contracts and application logic.

Dependencies

Start by installing our test runner, in this case jest:

yarn add -D jest

We'll need to install and run the Sandbox.

Test setup

Create a new file src/index.test.mjs with the imports we'll be using and an empty test suite to begin with:

import {
Contract,
ExtendedNote,
Fr,
Note,
computeSecretHash,
createPXEClient,
waitForPXE,
} from "@aztec/aztec.js";
import { createAccount } from "@aztec/accounts/testing";
import { TokenContract } from "@aztec/noir-contracts.js/Token";

const {
PXE_URL = "http://localhost:8080",
ETHEREUM_HOST = "http://localhost:8545",
} = process.env;

describe("token contract", () => {
// <tests go here>
});

Let's set up our test suite. We'll make sure the Sandbox is running, create two fresh accounts to test with, and deploy an instance of our contract. aztec.js provides the helper functions we need to do this:

setup
let owner, recipient, token;

beforeAll(async () => {
const pxe = createPXEClient(PXE_URL);
await waitForPXE(pxe);
owner = await createAccount(pxe);
recipient = await createAccount(pxe);

const initialBalance = 69;
token = await deployToken(owner, initialBalance, createLogger('e2e:sample_dapp'));
}, 120_000);
Source code: yarn-project/end-to-end/src/sample-dapp/index.test.mjs#L11-L23
tip

Instead of creating new accounts in our test suite, we can use the ones already initialized by the Sandbox upon startup. This can provide a speed boost to your tests setup. However, bear in mind that you may accidentally introduce an interdependency across test suites by reusing the same accounts.

Writing our test

Now that we have a working test environment, we can write our first test for exercising the transfer function on the token contract. We will use the same aztec.js methods we used when building our dapp:

test
it('increases recipient funds on transfer', async () => {
expect(await token.withWallet(recipient).methods.balance_of_private(recipient.getAddress()).simulate()).toEqual(0n);
await token.methods.transfer(recipient.getAddress(), 20).send().wait();
expect(await token.withWallet(recipient).methods.balance_of_private(recipient.getAddress()).simulate()).toEqual(
20n,
);
}, 30_000);
Source code: yarn-project/end-to-end/src/sample-dapp/index.test.mjs#L25-L33

In this example, we assert that the recipient's balance is increased by the amount transferred. We could also test that the owner's funds are decremented by the same amount, or that a transaction that attempts to send more funds than those available would fail.

Running our tests

We can run our jest tests using yarn. The quirky syntax is due to jest limitations in ESM support, as well as not picking up mjs file by default:

yarn node --experimental-vm-modules $(yarn bin jest) --testRegex '.*\.test\.mjs$'

Next steps

Have you written a contract from scratch? If not, follow a tutorial for writing contracts with Noir

Or read about the fundamental concepts behind Aztec Network and dive deeper into how things work.