3

I am writing test cases for my contract and have to delay the assertion check because it is time sensitive. getCompletedCampaigns() will have the address of the Campaign whose deadline has passed.

it("Time sensitive check", async () => {

    var deadLine = Math.round(Date.now() / 1000) + 3;
    let eventDetails = await contract.createCampaign("Campaign name",deadLine,
    {
        from: accounts[0]
    });

    addressFromEvent = eventDetails['logs'][1]['args']['campaignAddress'];

    async function checker() {
        let deployedCampaigns = await factory.getCompletedCampaigns();
        assert.equal(addressFromEvent, deployedCampaigns[0]);
    }

    function timeout(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function sleep() {
        await timeout(5000);
        return checker();
    }

    sleep();
});

The test passes even if the assertion is supposed to fail. The assertion happens after the test suite has finished executing all tests and forces the prompt to come out of truffle develop console because if it had failed. In the below testing I ve failed the test on purpose.

Contract: Testing CrowdCoin
    ✓ CampaignFactory deployment
    ✓ Create a new Campaign (168ms)
    ✓ Get ongoing Campaigns (246ms)
    ✓ Get completed Campaigns (189ms)


  4 passing (1s)

truffle(develop)> 
/home/vagrant/code/test/crowdcoin.test.js:82
            assert.equal(0, deployedCampaigns[1]);
          ^
AssertionError: expected 0 to equal '0x806ea81c279b6000b9fd9f14d2845dec87fc3544'
    at checker (/home/vagrant/code/test/crowdcoin.test.js:82:11)
    at process._tickCallback (internal/process/next_tick.js:68:7)

How do I make sure the test check happens along with time delay?

Sushant Kumar
  • 435
  • 7
  • 24

2 Answers2

5
it("Time sensitive check", async () => {

    var deadLine = Math.round(Date.now() / 1000) + 3;
    let eventDetails = await contract.createCampaign("Campaign name",deadLine,
    {
        from: accounts[0]
    });

    function timeout(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    await timeout(5000);

    addressFromEvent = eventDetails['logs'][1]['args']['campaignAddress'];
    let deployedCampaigns = await factory.getCompletedCampaigns();
    await assert.equal(addressFromEvent, deployedCampaigns[0]);
});

By moving the entire delay logic to a different method and all logical statements preceded by await, the execution of the said logical statements and test completion is not done unless timeout() has completed.

Sushant Kumar
  • 435
  • 7
  • 24
0

Actually you can try using time in @openzeppelin/test-helper to speed up your test case as you don't necessary wait for 3 secs running on this test case.

const { time } = require("@openzeppelin/test-helpers");

it("Time sensitive check", async () => {
    let duration = time.duration.seconds(3);
    let eventDetails = await contract.createCampaign("Campaign name",duration,
    {
        from: accounts[0]
    });

    await time.increase(duration);

    addressFromEvent = eventDetails['logs'][1]['args']['campaignAddress'];
    let deployedCampaigns = await factory.getCompletedCampaigns();
    await assert.equal(addressFromEvent, deployedCampaigns[0]);
});

which make more sense on testing timestamp in blockchain.

Doc: https://docs.openzeppelin.com/test-helpers/0.5/api#time

An example of how @openzeppelin team work on test case that you can look into: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/24a0bc23cfe3fbc76f8f2510b78af1e948ae6651/test/token/ERC20/utils/TokenTimelock.test.js

Elvis Wong
  • 348
  • 2
  • 8