Unit Testing in Truffle

There was already a test above in the code that created a person, so I just tried to delete that for my new tests.

it(“should prevent non-owners from deleting the person”, async function(){
let instance = await People.deployed();
await instance.deletePerson(‘0x7a601df2c5F0Fddc4073A2E36D8228Be8E3F44bf’);
});
it(“should let owner delete the person”, async function(){
let instance = await People.deployed();
await instance.deletePerson(‘0x976A4ca20eE911FeD7995d2e30FdD71D9BA8df95’);
});

1 Like

VALUE ASSIGNMENT

it("should match balance of contract with internal balance variable", async function(){
    let instance = await People.new();
    let variableBalance = 0;
    await instance.createPerson("Joe", 65, 190, {value: web3.utils.toWei("1", "ether")});
    variableBalance = web3.utils.toWei("1", "ether");
    let actualBalance = await web3.eth.getBalance(instance.address);
    assert(variableBalance === actualBalance, "Balances do not match");
  });
  it("should allow owner to withdraw balance", async function(){
    let instance = await People.deployed();
    let originalOwnerBalance = await web3.eth.getBalance(accounts[0]);
    await instance.withdrawAll();
    let newContractBalance = await web3.eth.getBalance(instance.address);
    let newOwnerBalance = await web3.eth.getBalance(accounts[0]);
    assert(newContractBalance === web3.utils.toWei("0", "ether"), "Contract balance is NOT zero!");
    assert(newOwnerBalance > originalOwnerBalance, "Owner did NOT receive withdrawed funds!");
  });
1 Like
it("should allow the owner to delete people", async function(){
    let instance = await People.new();
    await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}));
  });
  it("should not allow non-owner to delete people", async function(){
    let instance = await People.new();
    await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.fails(instance.deletePerson(accounts[2], {from: accounts[2]}), truffleAssert.ErrorType.REVERT);
  });
  it("should check the balance of the contract", async function(){
      let instance = await People.new();
      await instance.createPerson("Henk", 34, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
      let balance = await (web3.eth.getBalance(instance.address));
      console.log(balance);
      let floatBalance = parseFloat(balance);
      console.log(floatBalance);
      assert.equal(balance, floatBalance, "balances should be the same");

    });
    it("should check the differences in balances of the contract", async function(){
        let instance = await People.new();
        await instance.createPerson("Henk", 34, 160, {from: accounts[2], value: web3.utils.toWei("2", "ether")});
        let balance = await (web3.eth.getBalance(instance.address));
        console.log(balance);
        let floatBalance = parseFloat(balance);
        console.log(floatBalance);
        await truffleAssert.passes(balance == floatBalance, "balances should be the same");
      });
      it("should allow the owner to withdraw balance", async function(){
        let instance = await People.new();
        await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
        await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
        });
        it("should not allow a non-owner to withdraw balance", async function(){
          let instance = await People.new();
          await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
          await truffleAssert.fails(instance.withdrawAll({from: accounts[2]}), truffleAssert.ErrorType.REVERT);
        });
        it("owners balance should increase after withdrawal", async function(){
          let instance = await People.new();
          await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});

          let balanceBefore = parseFloat(await web3.eth.getBalance(accounts[0]));
          await instance.withdrawAll();
          let balanceAfter = parseFloat(await web3.eth.getBalance(accounts[0]));
          assert(balanceBefore < balanceAfter, "Owners balance was not increased after withdrawal");

        });

But I’m getting test failed messages in truffle:

  1. Contract: People
    should allow the owner to delete people:
    AssertionError: Failed with Error: Returned error: VM Exception while processing transaction: revert
    at passes (node_modules/truffle-assertions/index.js:142:11)
    at process._tickCallback (internal/process/next_tick.js:68:7)

  2. Contract: People
    should allow the owner to withdraw balance:
    AssertionError: Failed with Error: Returned error: VM Exception while processing transaction: revert
    at passes (node_modules/truffle-assertions/index.js:142:11)
    at process._tickCallback (internal/process/next_tick.js:68:7)

  3. Contract: People
    owners balance should increase after withdrawal:
    Error: Returned error: VM Exception while processing transaction: revert
    at PromiEvent (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
    at TruffleContract.withdrawAll (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
    at Context. (test/PeopleTest.js:83:26)
    at process._tickCallback (internal/process/next_tick.js:68:7)

  4. Contract: People
    should reset balance to 0 after withdrawal:
    Error: Returned error: VM Exception while processing transaction: revert
    at PromiEvent (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/promievent.js:6:1)
    at TruffleContract.withdrawAll (/usr/local/lib/node_modules/truffle/build/webpack:/packages/contract/lib/execute.js:158:1)
    at Context. (test/PeopleTest.js:92:20)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Even with the code from Filip it keep giving me the same errors. maybe I did something wrong with the owner statement in the Owner contract?

Hey @Nicksta

You are hitting revert () statements in your smart contract.
Please post your project directory on github and give me the link, I will take a look.

Cheers,
Dani

1 Like

Happened at 7:03 during Testing for Errors, Unit Testing video

Hey @Lucus

Follow this faq to fix the issue: FAQ - How to downgrade Node.Js

Happy coding,
Dani

1 Like

thank you for the quick response!

1 Like

Here my tryout solution :

1 Like

Hi, thanks for you answers :slight_smile:

the question number 3 is related to the unit testing done in the course.
So it’s the code that filip explains https://github.com/filipmartinsson/solidity-201/blob/master/finaltests.js

basically on line 19 of the code instead of

await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});

to understand better how accounts works I tried

await instance.createPerson("Bob", 65, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether")});

From your answer in the first case person is created with accounts[0] since it is not specified. In this second case is created with accounts[1]. But I don’t understand why I get the error

thanks :slight_smile:

it(“should increase balance”,async function(){
let instance= await people.deployed();
let lastB=web3.eth.getBalance(“0x79ADF13DCba784F5e14ea6AABF7026b781b1Bc9E”);
await instance.createPerson(“bob”,65,190,{value:web3.utils.toWei(“1”,“ether”)});
assert(web3.eth.getBalance(“0x79ADF13DCba784F5e14ea6AABF7026b781b1Bc9E”)>=lastB);
})

it(“should let the owner withdraw”,async function(){
let instance= await people.deployed();
await truffleAssert.passes(instance.withdrawAll({from:accounts[0]}), truffleAssert.ErrorType.REVERT);

})

Hey @enrico

Please post your smart contract too.

Cheers,
Dani

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

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

it("shouldn't create person 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);
di 150
});


it("should't create 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 correctly", async function(){
  let instance = await People.deployed();
    await instance.createPerson("Bob", 65, 190, {from: accounts[1], 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("non owner can't delete people", async function(){
    let instance = await People.deployed();
    await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.fails(
      instance.deletePerson(accounts[2], {from: accounts[2]}), truffleAssert.ErrorType.REVERT);
  })


  it("owner have to be able to delete account", async function(){
    let instance = await People.deployed();

    await truffleAssert.passes(instance.deletePerson(accounts[2], {from: accounts[0]}), truffleAssert.ErrorType.REVERT);
  })

  it("controllo che balance si aggiorni quando creo persona", async function(){
    let instance = await People.new();
    await instance.createPerson("Lisa", 35, 160, {value: web3.utils.toWei("1", "ether")});
    let balance = await instance.balance();
    let floatBalance = parseFloat(balance);
    let realBalance = await web3.eth.getBalance(instance.address); 
    await truffleAssert.passes(floatBalance == realBalance && floatBalance == web3.utils.toWei("1", "ether"));
   
  })

  it("should allow the owner to withdraw balance", async function(){
    let instance = await People.new();
    await instance.createPerson("Lisa", 35, 160, {value: web3.utils.toWei("1", "ether")});
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
  })

it("should not allow a non-owner to withdraw balance", async function(){
  let instance = await People.new();
  await instance.createPerson("Lisa", 35, 160, {value: web3.utils.toWei("1", "ether")});
  await truffleAssert.fails(instance.withdrawAll({from: accounts[2]}), truffleAssert.ErrorType.REVERT);
})


it("owners balance should increase after withdrawal", async function(){
  let instance = await People.new();
  await instance.createPerson("Lisa", 35, 160, {value: web3.utils.toWei("1", "ether")});
  let balanceBefore = parseFloat(await web3.eth.getBalance(accounts[0]));
    await instance.withdrawAll();
    let balanceAfter = parseFloat(await web3.eth.getBalance(accounts[0]));
    assert(balanceBefore < balanceAfter, "Owners balance was not increased after withdrawal");
 })

 it("should reset balance to 0 after withdrawal", async function(){
   let instance = await People.new();
   await instance.createPerson("Lisa", 35, 160, {value: web3.utils.toWei("1", "ether")});
  await instance.withdrawAll();
   let balance = await instance.balance();
   let floatBalance = parseFloat(balance);
   let realBalance = await web3.eth.getBalance(instance.address); 
   assert (floatBalance == realBalance && floatBalance == web3.utils.toWei("0", "ether"));


})




});

@enrico

I need the smart contract, these are the tests :smiley:

Cheers,
Dani

2 Likes

sorry, here is the code:

import "./Ownable.sol";
pragma solidity 0.5.16;

contract People is Ownable{

    struct Person {
      uint id;
      string name;
      uint age;
      uint height;
      bool senior;
    }

    event personCreated(string name, bool senior);
    event personDeleted(string name, bool senior, address deletedBy);

    uint public balance;

    modifier costs(uint cost){
        require(msg.value >= cost);
        _;
    }

    mapping (address => Person) private people;
    address[] private creators;

    function createPerson(string memory name, uint age, uint height) public payable costs(1 ether){
      require(age < 150, "Age needs to be below 150");
      require(msg.value >= 1 ether);
      balance += msg.value;

        //This creates a person
        Person memory newPerson;
        newPerson.name = name;
        newPerson.age = age;
        newPerson.height = height;

        if(age >= 65){
           newPerson.senior = true;
       }
       else{
           newPerson.senior = false;
       }

        insertPerson(newPerson);
        creators.push(msg.sender);

        assert(
            keccak256(
                abi.encodePacked(
                    people[msg.sender].name,
                    people[msg.sender].age,
                    people[msg.sender].height,
                    people[msg.sender].senior
                )
            )
            ==
            keccak256(
                abi.encodePacked(
                    newPerson.name,
                    newPerson.age,
                    newPerson.height,
                    newPerson.senior
                )
            )
        );
        emit personCreated(newPerson.name, newPerson.senior);
    }
    function insertPerson(Person memory newPerson) private {
        address creator = msg.sender;
        people[creator] = newPerson;
    }
    function getPerson() public view returns(string memory name, uint age, uint height, bool senior){
        address creator = msg.sender;
        return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior);
    }


    function deletePerson(address creator) public onlyOwner {
      string memory name = people[creator].name;
      bool senior = people[creator].senior;

       delete people[creator];
       assert(people[creator].age == 0);
       emit personDeleted(name, senior, owner);
   }
   function getCreator(uint index) public view onlyOwner returns(address){
       return creators[index];
   }
   function withdrawAll() public onlyOwner returns(uint) {
       uint toTransfer = balance;
       balance = 0;
       msg.sender.transfer(toTransfer);
       return toTransfer;
   }

}

Here is my code. Thanx for the course!

1 Like

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

contract(“People”, async function(accounts){
it(“Should set senior status correctly”, async ()=>{
let instance = await People.deployed();
await instance.createPerson(“Bob”, 65, 190, {value: web3.utils.toWei(“1”, “ether”), from: accounts[0]});
let result = await instance.getPerson();
assert(result.senior === true, “Senior level not set”);
});
it(“Shouldn’t be delete by an account which is not the owner of the contract”, async ()=>{
let instance = await People.deployed();
await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}),
truffleAssert.ErrorType.REVERT);
});
it(“Should be able to delete your own account”, async ()=>{
let instance = await People.deployed();
let person = await instance.getPerson();
assert(person.age.toNumber() !== 0 && person.name !== ‘’,
“A person should exist and have age and name set before this test is executed”);
await instance.deletePerson(accounts[0], {from: accounts[0]});
person = await instance.getPerson();
assert(person.age.toNumber() === 0 && person.name === ‘’,
“Delete person didn’t have erase the person correctly”);
});
});

1 Like

Value Assignment:

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

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

let instance;

beforeEach(async ()=> {
	instance = await People.new();
});

it("Should have a correct balance", async ()=>{
	let old_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes(instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1.2", "ether"), from: accounts[0]}),
								"createPerson method should have minimun ether");
	let new_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes((new_balance > web3.utils.fromWei(old_balance, "ether"), "New balance should be greater when a new person is added"));
	let var_balance = await instance.balance();
	await truffleAssert.passes((parseFloat(var_balance) > new_balance,
		"New balance should be greater when a new person is added"));
});

it("Should be able to withdraw", async ()=>{
	let old_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes(instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1.2", "ether"), from: accounts[0]}),
								"createPerson method should have minimun ether");
	let new_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes(new_balance > old_balance, "New balance should be greater when a new person is added");
	await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}),
							"Contract owner should be able to withdraw");
	await truffleAssert.passes(new_balance === old_balance , "new balance should be equal to 0 when fund a retrieved");
});

it("Shouldn't be able to withdraw", async ()=>{
	let old_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes(instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1.2", "ether"), from: accounts[0]}),
								"createPerson method should have minimun ether");
	let new_balance =  await web3.eth.getBalance(instance.address);
	await truffleAssert.passes(new_balance > old_balance, "ether", "New balance should be greater when a new person is added");
	await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}),
							  truffleAssert.ErrorType.REVERT);
	await truffleAssert.passes(new_balance > old_balance , "new balance should be equal when withdraw fail");
});

});

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

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

  console.log("Account1: " + accounts[1]);

  it("Should create a person as non-owner of contract", async function (){

    let instance = await People.deployed();
    await truffleAssert.passes(instance.createPerson("Philip", 65, 190, {value: web3.utils.toWei("1","Ether"), from: accounts[1]}),"Created person who is non owner");

  });

  it("Shouldn't allow non-owner to delete a person", async function (){

    let instance = await People.deployed();
    await truffleAssert.fails(instance.deletePerson(accounts[1],{from: accounts[1]}),truffleAssert.ErrorType.REVERT)

  });

  it("Should allow owner to delete a person", async function (){

    let instance = await People.deployed();
    await truffleAssert.passes(instance.deletePerson(accounts[1],{from: accounts[0]}))

  });

  it("Shouldn't allow a non-owner to look up a creator's address", async function (){

    let instance = await People.deployed();
    await truffleAssert.fails(instance.getCreator(0,{from: accounts[1]}),truffleAssert.ErrorType.REVERT)

  });

  it("Should allow an owner to look up a creator's address", async function (){

    let instance = await People.deployed();
    await truffleAssert.passes(instance.getCreator(0,{from: accounts[0]}))

  });

  it("Shouldn't allow a non-owner to withdraw funds", async function (){

    let instance = await People.deployed();
    await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}),truffleAssert.ErrorType.REVERT)

  });

  it("Should allow an owner to withdraw funds", async function (){

    let instance = await People.deployed();
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}))

  });

});
1 Like

My solution for the unit testing of the money functions.

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

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

  let instance;

  before(async function(){

    instance = await People.new();

  });

  it("Should have 1 Ether after being sent 1 Ether", async function (){

    await instance.createPerson("Philip", 65, 190, {value: web3.utils.toWei("1","Ether"), from: accounts[1]});
    let addr = instance.address;
    let blockchain_balance = await web3.eth.getBalance(instance.address);
    let contract_state_balance = await instance.balance();
    assert (blockchain_balance === web3.utils.toWei("1","Ether"),"Blockchain balance is 1 Ether");
    assert (contract_state_balance == blockchain_balance,"Contract state balance is 1 Ether");

  });

  it("Should not allow withdrawal for non owner", async function (){

    await instance.createPerson("Philip", 65, 190, {value: web3.utils.toWei("1","Ether"), from: accounts[1]});
    await truffleAssert.fails(instance.withdrawAll({from: accounts[1]}),truffleAssert.ErrorType.REVERT)

  });

  it("Should let the owner withdraw the 1 Ether that's in contract", async function (){

    await instance.createPerson("Philip", 65, 190, {value: web3.utils.toWei("1","Ether"), from: accounts[1]});
    let pre_withdraw_balance = await instance.balance();
    await truffleAssert.passes(instance.withdrawAll());
    let post_withdraw_balance = await instance.balance();
    let post_blockchain_balance = await web3.eth.getBalance(instance.address);
    assert (post_blockchain_balance == 0,"Contract blockchain balance is zero");
    assert (post_withdraw_balance == 0,"Contract state balance is zero");
    
  });

});
1 Like