Unit Testing in Truffle

Hi all,
I have a little trouble with the Value Assignment.

After the migration I want to console.log the following while running the test:
-owner address
-owner balance
-contract address
-contract balance

So I have written following test code:

const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");

contract("People", async function(accounts){

    let instance;

    before(async function(){
      instance = await People.deployed();
      //beforeEach()
      //afterEach()
      //after()
    });
  it("should not create a person with age over 150 years", async function(){
    //BEFORE EACH*
  //  let instance = await People.deployed();
    await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether" )}), truffleAssert.ErrorType.REVERT);
  });
  it("should not create a person without payment", async function(){
    await truffleAssert.fails(instance.createPerson("Booztb", 50, 190, {value: 1000}, truffleAssert.ErrorType.REVERT));
  });
  it("should set senior status correctly", async function(){
    await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether" )});
    let result = await instance.getPerson();
    assert(result.senior === true, "Senior level not set");
  });
  it("should set age correctly", async function(){
    let result = await instance.getPerson();
    assert(result.age.toNumber() === 65, "Age not set correctly");
  });
  it("should not allow anybody aside the owner to delete people", async function(){
    await instance.createPerson("jeff", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether" )});
    await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
  });
  it("should allow Owner to delete Person", async function(){
    let instance = await People.new();
//    let instance = await People.deployed();
  await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}));
  });

  it("should check when person is added the balance of the contract will increase", async function(){
    await instance.createPerson("jeff", 65, 190, {from: accounts[0], value: web3.utils.toWei("1", "ether" )});

    let owner = accounts[0];
    let balance = await web3.eth.getBalance(owner);
    let contractBalance = People.address;
    console.log("deployed address of owner " + owner);
    console.log("address of contract " + People.address);

    web3.eth.getBalance(contractBalance).then(function(balance){
      console.log("Balance of contract   " + balance);
    })

    web3.eth.getBalance(owner).then(function(balance){
      console.log("Balance of owner   " + balance);
    })

    })

});

so far everything went well except the contract address was not the one ganache console as well as the ganache app showed after running the migration.

Maybe some can take a look and help.
THX

Hi @jimmy2k
I don’t see where you are initializing your instance, are you using a “beforeEach()” in your test ?
If you want to use the contract deployed you should use

 let instance = await People.deployed();

At the beginning of your test, otherwise if you want to deploy a new contract to have a clean state you can do a People.new()

Hey @gabba,

I have inserted my full code above so hopefully it helps!

Hi again @jimmy2k
I guess you are talking about the contract you had deployed and the one you are testing.
Every time the test suite is launch a new contract is deployed. I add few console log and this is what i can see:

When a test is launch i have a first address

Contract created: 0x61ad59ac026448bfecefef781f3fb063800a97e6
  Gas usage: 225237
  Block Number: 169
  Block Time: Mon Feb 17 2020 22:55:08

This is the Migration contract (imo)

Then your contract instance:

    before(async function(){
      instance = await People.deployed();
      console.log("address of contract " + instance.address);
    });
  Contract created: 0x4b2af984beb19d8e26b69a9fac91361a6e22e6ce
  Gas usage: 986937
  Block Number: 171
  Block Time: Mon Feb 17 2020 22:55:09

Finally an other contract is create when you are using new:

  it("should allow Owner to delete Person", async function(){
    let instance = await People.new();
    console.log("2 address of contract " + instance.address);
  await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}));
  });
  Contract created: 0x6b620ac908a96ca85e55f8123bb8aef80c04dd71
  Gas usage: 986937
  Block Number: 177
  Block Time: Mon Feb 17 2020 22:55:09

This last one is local to your scope test.

So all of those contracts are new instances, and are not related to the main contract you already had deploy (imo again :slight_smile: )

1 Like

hey @gabba,

thank you for your help! :slight_smile: I think I understood it!
but still I wonder why I the address of the contract “People” in Ganache is not the same as in the console!?
And can I find the contract address which was created in truffle anywhere in ganache?

My idea for the value assignent test was to compare the balance of the contract with the balance of the owner…

The contract’s address i had post are from ganache, i m using ganache-cli but you can get those values in the transaction page in ganache gui. The contract creation are shown in red.
If you want to compare the user balance and the contract balance you can have a look at my post in this forum, i posted an example.
https://forum.toshitimes.com/t/unit-testing-in-truffle/10053/63.

    let accountBalanceAfterTransaction = await web3.eth.getBalance(accounts[0]);
    const contractBalanceAfterTransaction = await web3.eth.getBalance(ContractInstance.address);

When you are testing you are using a new environment you are never testing the current deployed contract. So if you want to test the balance, you have to move fund in your test first to modify your contract value then test the balances.

“but still I wonder why I the address of the contract “People” in Ganache is not the same as in the console!?”
It is easier this way otherwise every time you run your test you will have a different result if you interact with your contract. Tests instance are separate.

1 Like

Solution for onlyOwner modfier testing.

it(“Delete must be called from contract owner”, async function() {
let instance = await People.deployed();
await truffleAssert.fails(instance.deletePerson(accounts[1], {from:accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it(“Delete must be called from contract owner”, async function() {
let instance = await People.deployed();
await assert(instance.deletePerson(accounts[1], {from:accounts[0]}));
});

1 Like

thank you! I did not know that the testings are always in a new environment…now it makes sense of course. still long way to got for me and I have plenty of questions,

I really appreciate your help! :slight_smile:

1 Like

Solution to Value assignment

it(“Should have an equal balance”, async function(){
let contractbalance = await instance.balance();
let chainbalance = await web3.eth.getBalance(People.address);
await assert(contractbalance == chainbalance);
});

it("Shouldn't allow anyone except the owner to withdraw", async function(){
  let contractbalance = await instance.balance();
  truffleAssert.fails(instance.withdrawAll({from:accounts[2]}),truffleAssert.ErrorType.REVERT);
});
it("Should Allow the owner to withdraw", async function(){
  let contractbalance = await instance.balance();
  assert(instance.withdrawAll({from:accounts[0]}));
});
it("should have added value to owner", async function(){
  let instance = await People.new();
  let ownerbalance = await web3.eth.getBalance('0xef532B610CCC9DffDe4Bbadb0810e09641281b2B');
  await instance.createPerson("Bob",20,190, {value: web3.utils.toWei("1","ether")})
  await instance.withdrawAll({from:accounts[0]});
  assert(ownerbalance = parseInt(web3.utils.toWei("1","ether")));
});

Hi @CryptoDev
I m not sure to understand your last test, is this address 0xef532B610CCC9DffDe4Bbadb0810e09641281b2B

The accounts[0] address ? If you withdraw everything the assert should fail ?
In your assert you should use ‘===’ because with ‘=’ you are assigning a value your are not testing the result.

thanks for pointing that out figured it out my issue was thinking that accounts start with 0 eth when ganche accounts have 100 eth so changed it to this

it("should have added value to owner", async function(){
      let instance = await People.new();
      await instance.createPerson("Bob",20,190, {value: web3.utils.toWei("1","ether"), from:accounts[1]});
      let beforeownerbalance = await web3.eth.getBalance(accounts[0]);
      await instance.withdrawAll({from:accounts[0]});
      let afterownerbalance = await web3.eth.getBalance(accounts[0]);
      assert(afterownerbalance > beforeownerbalance ,"Owner value has not increased");
    });
1 Like

Hey guys, hey @filip

I want to check if the balance increases in my last test, while also console.log the balance before and after the withdrawl. unfortunately the balance after testing the withdrawl is equal. so the test does not pass…
maybe someone can take a look…

const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");

contract("People", async function(accounts){
 let owner = accounts[0];
    let instance;

    before(async function(){
      instance = await People.deployed();
      //beforeEach()
      console.log("address of contract " + instance.address);
      //afterEach()
      //after()
    });
  it("should not create a person with age over 150 years", async function(){
    //BEFORE EACH*
  //  let instance = await People.deployed();
    await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether" )}), truffleAssert.ErrorType.REVERT);
  });
  it("should not create a person without payment", async function(){
    await truffleAssert.fails(instance.createPerson("Booztb", 50, 190, {value: 1000}, truffleAssert.ErrorType.REVERT));
  });
  it("should set senior status correctly", async function(){
    await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether" )});
    let result = await instance.getPerson();
    assert(result.senior === true, "Senior level not set");
  });
  it("should set age correctly", async function(){
    let result = await instance.getPerson();
    assert(result.age.toNumber() === 65, "Age not set correctly");
  });
  it("should not allow anybody aside the owner to delete people", async function(){
    await instance.createPerson("jeff", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether" )});
    await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[3]}), truffleAssert.ErrorType.REVERT);
  });
  it("should allow Owner to delete Person", async function(){
    let instance = await People.new();
 //console.log("address of contract " + instance.address);
    await truffleAssert.passes(instance.deletePerson(accounts[1], {from: owner}));
  });

  it("should allow the owner to withdrawl balance", async function(){
    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: accounts[2], value: web3.utils.toWei("1", "ether" )});
    await truffleAssert.passes(instance.withdrawAll({from: owner}), truffleAssert.ErrorType.REVERT);
  })
   web3.eth.getBalance(owner).then(function(balance){
    console.log("Balance of owner before withdrawl  " + balance);
  })
  it("owner balance should increase after withdrawl", async function(){

    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: owner, value: web3.utils.toWei("1", "ether" )});
    let balanceBefore =  owner.balance;
    await instance.withdrawAll();
    let balanceAfter =  owner.balance;
    console.log("address of owner " + owner);
    assert(balanceAfter > balanceBefore, "Owners balance was not increased");
  })
   web3.eth.getBalance(owner).then(function(balance){
    console.log("Balance of owner after withdrawl   " + balance);
  })
});

I have also added another function to the people.sol contract:

   function getBalance() public returns (uint){
    return address(this).balance;
   }

Thank you!

//Owner by dafault is set to accounts[0], therefore executing any onlyOwner function from other accounts should revert

const People = artifacts.require(“People”);
const truffleAssert = require(“truffle-assertions”);

contract(“People”, async function(accounts){

it("should not be possible to delete person by not the owner", async function(){
    let instance = await People.deployed();
    await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});
    await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);

});

it("should not be possible to get creator by not the owner", async function(){
    let instance = await People.deployed();
    await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
    await truffleAssert.fails(instance.getCreator(0, {from: accounts[1]}), truffleAssert.ErrorType.REVERT);

});

    it("should not be possible to withdrawl all balance by not the owner", async function(){
    let instance = await People.deployed();
    await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}), truffleAssert.ErrorType.REVERT);

});

});

1 Like

const People = artifacts.require(“People”);
const truffleAssert = require(“truffle-assertions”);

contract(“People”, async function(accounts){

let instance

//function called before all tests
before(async function() {
    instance = await People.deployed();
});


it("should match balance of the contract with balance state variable after person is added", async function(){
    await instance.createPerson("Bob", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
    let stateVariableBalance = await instance.balance();
    let contractBalance = await web3.eth.getBalance(instance.address);
    assert(parseInt(stateVariableBalance) === parseInt(contractBalance), "Balance do not match");

});

it("should not allow to withdraw all balance by not the owner", async function(){
    await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}), truffleAssert.ErrorType.REVERT);

});

it("should allow to withdrawl all balance by the owner", async function(){
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));

});

it("should set balance to zero after funds are withdraw", async function(){
    await instance.createPerson("Bob", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
    let stateVariableBalance = await instance.balance();
    assert(parseInt(stateVariableBalance) === 0, "Balance not fully withdraws");

});

it("should increase balance of owner after funds are withdraw", async function(){
    await instance.createPerson("Bob", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
    let ownerBalanceBeforeWithdraw = await web3.eth.getBalance(accounts[0]);
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
    let ownerBalanceAfterWithdraw = await web3.eth.getBalance(accounts[0]);
    assert(parseInt(ownerBalanceBeforeWithdraw) < parseInt(ownerBalanceAfterWithdraw), "Owner balance after nwithdraw not increased");

});

});

1 Like

Hi @jimmy2k

if you console log the result of owner.balance you ll see that it s undefined because balance is not a function. You can test the account balance with web3 api


    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: owner, value: web3.utils.toWei("1", "ether" )});
    let balanceBefore =  await web3.eth.getBalance(owner);
    await instance.withdrawAll();
    let balanceAfter =  await web3.eth.getBalance(owner);
    console.log("address of owner " + owner);
    assert(balanceAfter > balanceBefore, "Owners balance was not increased");
  })

This way your test will works :wink:

1 Like

yes it is a function. i get same results with your code…both balances are the same…

Hi @jimmy2k

This output is the same because you are running it outside of the test, each test have is own scope

   web3.eth.getBalance(owner).then(function(balance){
    console.log("Balance of owner before withdrawl  " + balance);
  })

As you can see in my screenshot the output of the 2 console log are different.

    console.log(balanceAfter);
    console.log(balanceBefore);

1 Like

Hi @gabba,

ok now I get it. :slight_smile:
Again, Thank you very much!! :slight_smile:

1 Like

Here my Value Assignment Tests finally :

it("should not allow anybody aside the owner to delete people", async function(){
    await instance.createPerson("jeff", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether" )});
    await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[3]}), truffleAssert.ErrorType.REVERT);
  });
  it("should allow Owner to delete Person", async function(){
    let instance = await People.new();
 //console.log("address of contract " + instance.address);
    await truffleAssert.passes(instance.deletePerson(accounts[1], {from: owner}));
  });
  it("should allow the owner to withdrawl balance", async function(){
    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: accounts[2], value: web3.utils.toWei("1", "ether" )});
    await truffleAssert.passes(instance.withdrawAll({from: owner}), truffleAssert.ErrorType.REVERT);
  })
   web3.eth.getBalance(owner).then(function(balance){
    console.log("Balance of owner before withdrawl  " + balance);
  })
  it("owner balance should increase after withdrawl", async function(){
    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: owner, value: web3.utils.toWei("1", "ether" )});
    let balanceBefore =  await web3.eth.getBalance(owner);
    await instance.withdrawAll();
    let balanceAfter =  await web3.eth.getBalance(owner);
    console.log("address of owner " + owner);
    console.log("Owner balance before withdrawAll " + balanceBefore);
    console.log("Owner balance after withdrawAll " + balanceAfter);
    assert(balanceAfter > balanceBefore, "Owners balance was not increased");
  })
   web3.eth.getBalance(owner).then(function(balance){
    console.log("Balance of owner after withdrawl   " + balance);
  })
  it("should reset a balance to 0 after withdrawl", async function(){
    let instance = await People.new();
    await instance.createPerson("Anna", 65, 190, {from: owner, value: web3.utils.toWei("1", "ether" )});
    await instance.withdrawAll();
    let balance = await instance.balance();
    console.log("Owner balance after withdrawAll " + balance);
    let balanceOfBlockchain = await web3.eth.getBalance(instance.address);
    console.log("Owner Balance on Blockchain " + balanceOfBlockchain);
    assert(balance == web3.utils.toWei("0", "ether") && balance == balanceOfBlockchain, "Contract Balance is not 0 after withdrawAll or balances do not match");
  })
});
     web3.eth.getBalance(contractBalance).then(function(balance){
      console.log("Balance of contract   " + balance);
    })

    web3.eth.getBalance(owner).then(function(balance){
      console.log("Balance of owner   " + balance);
    })*/

1 Like

Solving the first assignment taught me how to call functions from different accounts on Ganache. It took me a while to figure out, but I searched on the Ethereum Stack Exchange and found how to do it.

const truffleAssert = require("truffle-assertions");

contract("People", (accounts) => {
    it("shouldn't create a person with age over 150 years", async function(){
        let instance = await People.deployed();
        await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
    });
    it("shouldn't create a person without payment", async function(){
        let instance = await People.deployed();
        await truffleAssert.fails(instance.createPerson("Bob", 50, 190, {value: 1000}), truffleAssert.ErrorType.REVERT);
    });
    it("should set senior status corrrectly", async function(){
        let instance = await People.deployed();
        await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});
        let result = await instance.getPerson();
        assert(result.senior === true, "Senior level not set");
    });
    it("should set age correctly", async function(){
        let instance = await People.deployed();
        let result = await instance.getPerson();
        assert(result.age.toNumber() === 65, "Age not set correctly");
    });
    it("shouln't allow someone that is not the owner to delete a person", async function(){
        let instance = await People.deployed();
        await instance.createPerson("Bob", 50, 190, {from: accounts[0], value: web3.utils.toWei("1", "ether")});
        await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}));
    });
    it("should allow the owner to delete a person", async function(){
        let instance = await People.deployed();
        await instance.createPerson("Bob", 50, 190, {from: accounts[0], value: web3.utils.toWei("1", "ether")});
        await instance.deletePerson(accounts[0], {from: accounts[0]});
    })
});```
2 Likes