Hi, I’m wondering if there’s a way to automate test for testnet in a similar way to testing on a local blockchain with test-environment and test-helpers?
Hi @minhdinh1,
With OpenZeppelin Test Environment you can fork an existing blockchain (such as mainnet or a public testnet) and run your tests against that network.
See the documentation for details on configuring fork: https://docs.openzeppelin.com/test-environment/0.1/getting-started#fork_and_unlocked_accounts
In order to fork an existing blockchain, do I need to deploy my contract up to the testnet first and use the block number after? And what does unlocked-accounts mean in the documentation you mentioned.
Sorry, I’m still new to smart contract testing
Hi @minhdinh1,
Your tests will deploy your contracts to the local fork of the blockchain.
unlocked_accounts
is an array of accounts that you want to unlock so that you can send transactions from these accounts.
Hi,
I’ve tried changing the test environment config in test-environment.config.js to fork from rinkeby testnet but it all of the test just fail at the setup token stage with this error.
1) LuniverseGluwacoin_Initialization
“before each” hook for “token name is LuniverseGluwacoin”:
Uncaught Error: Unhandled server error
at Object.default_1 [as default] (node_modules/@openzeppelin/test-environment/src/setup-ganache.ts:69:15)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at /mnt/c/Work/WSL_files/Luniverse-Gluwacoin/node_modules/@openzeppelin/test-environment/src/test-provider.ts:20:19
at run (node_modules/p-queue/dist/index.js:163:29)
Is there any more steps that I need to take to successfully run my test code on rinkeby testnet the same way it ran on the local blockchain?
My node packages version are:
npm 6.14.6
truffle v5.1.49
mocha 8.2.0
test-helper 0.5.7
test-environment 0.1.5
Hi @minhdinh1,
If your tests run locally then you just need to change your test-environment.config.js
to include what you want to fork. As per: https://docs.openzeppelin.com/test-environment/0.1/getting-started#fork_and_unlocked_accounts
I used Infura, but you could use Alchemy or another provider, see: https://docs.openzeppelin.com/learn/connecting-to-public-test-networks#accessing-a-testnet-node.
Testing against a fork takes time, so I recommend increasing the timeout.
Please find below a simple example I used:
test-environment.config.js
// test-environment.config.js
const { infuraProjectId, } = require('./secrets.json');
module.exports = {
node: { // Options passed directly to Ganache client
fork: `https://rinkeby.infura.io/v3/${infuraProjectId}`, // An url to Ethereum node to use as a source for a fork
},
};
secrets.json
I keep my Infura Project ID (or other API key secret) in secrets.json
but you could use any secret keeping approach ( don’t commit any secrets to version control)
{
"infuraProjectId": "MY INFURA PROJECT ID"
}
package.json
Testing against a fork is slow, so recommend increasing the timeout when running mocha
.
{
...
"scripts": {
"test": "mocha --exit --recursive --timeout 10000"
},
...
}
Box.sol
From: https://docs.openzeppelin.com/learn/developing-smart-contracts#first-contract
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Box {
uint256 private value;
// Emitted when the stored value changes
event ValueChanged(uint256 newValue);
// Stores a new value in the contract
function store(uint256 newValue) public {
value = newValue;
emit ValueChanged(newValue);
}
// Reads the last stored value
function retrieve() public view returns (uint256) {
return value;
}
}
Box.test.js
From: https://docs.openzeppelin.com/learn/writing-automated-tests#test-environment
// test/Box.test.js
// Load dependencies
const { accounts, contract } = require('@openzeppelin/test-environment');
const { expect } = require('chai');
// Load compiled artifacts
const Box = contract.fromArtifact('Box');
// Start test block
describe('Box', function () {
const [ owner ] = accounts;
beforeEach(async function () {
// Deploy a new Box contract for each test
this.contract = await Box.new({ from: owner });
});
// Test case
it('retrieve returns a value previously stored', async function () {
// Store a value - recall that only the owner account can do this!
await this.contract.store(42, { from: owner });
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await this.contract.retrieve()).toString()).to.equal('42');
});
});
Test
$ npm run test
> minhdinh1@1.0.0 test /home/abcoathup/projects/forum/minhdinh1
> mocha --exit --recursive --timeout 10000
Box
✓ retrieve returns a value previously stored (397ms)
1 passing (5s)
Thanks, I’m able to run my local tests on the testnet now.
I think the reason why my tests failed before is because settings that are caused through migrations and manually deploying and running contract functions to test on the testnet.
I manage to run my test on testnet by resetting the project to the point before I manually do the things I mentioned above.
Hi @minhdinh1,
Glad to hear that you are up and running with your tests.
You could deploy any contracts that you need in a before
or beforeEach
in your tests.