Unit Testing in Truffle

Hey @Samy

My bad I misunderstood your issue.
I think I found the error anyway.

In your test it('should not allow non-owner to delete people', async () => { you are sending the tx with accounts[0] which is the owner, therefore it does not fail.

I think your idea was to send the transaction with accounts[1] (or any account != accounts[0]).

Try this one

   it('should not allow non-owner to delete people', async () => {
     await instance.createPerson('Sam5', 30, 170, { from: accounts[1], value: web3.utils.toWei('1', 'ether') });
     truffleAssert.fails(instance.deletePerson(accounts[1],{from:accounts[1]}), truffleAssert.ErrorType.REVERT);
   });

Happy coding,
Dani

That was the idea indeed. Thanks a lot!

1 Like

This is my solution for the Owner test Assigment(delete function)


test running
image

changing to another account (not the owner )


test running

1 Like

My test for balances

image

1 Like

Could someone please tell me why I’m getting the error that the truffle-assertions module isn’t found? I’ve installed it w npm and I’ve “required” it at the top of my test file. Thank you

https://github.com/MBurtonshaw/blockchain_practice/tree/main/Helloworld

This wasn’t that easy but I understand better now…

});
  it("should not allow non owner delete perosn", async function(){
    let instance = await People.deployed();
    await instance.createPerson("Zala", 25, 180, {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.deployed();
    await truffleAssert.passes(accounts[1], {from: accounts[0]});
  });
});
1 Like

Hi Filip,
I’m getting this error when I execute the first example unit test. Do I need to downgrade node.js to a different version? I’m running Node.js v14.15.0.

TypeError [ERR_INVALID_REPL_INPUT]: Listeners for uncaughtException cannot be used in the REPL
at process. (repl.js:307:15)
at process.emit (events.js:327:22)
at process.emit (C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\build\webpack:~\source-map-support\source-map-support.js:465:1)
at processEmit [as emit] (C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\build\webpack:~\signal-exit\index.js:155:1)
at _addListener (events.js:358:14)
at process.addListener (events.js:406:10)
at Runner.run (C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\node_modules\mocha\lib\runner.js:868:11)
at Mocha.run (C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\node_modules\mocha\lib\mocha.js:612:17)
at C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\test.js:128:1
at new Promise ()
at Object.run (C:\Users\Mark\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\core\lib\test.js:127:1)
at runMicrotasks ()
at processTicksAndRejections (internal/process/task_queues.js:93:5)

My solution to the Owner test Assignment:

it(“Creates new person by non-contract owner and not able to delete people”, async function(){
await instance.createPerson(“Victor”, 40, 170, {from: accounts[1],value: web3.utils.toWei(“1”, “ether”)});
await truffleAssert.fails(
instance.deletePerson(accounts[1], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it(“Only the Owner should delete people”, async function(){
await instance.createPerson(“Victor”, 41, 171, {from: accounts[1], value: web3.utils.toWei(“1”, “ether”)});
await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}));
});

1 Like

Hey @mburtonshaw

I cloned your repo and I am able to run your test correctly.
Please cd into your root directory and try again npm i truffle-assertions

Let me know.

1 Like

Hey @mvernon

Downgrade node as explained here: FAQ - How to downgrade Node.Js

Should work correctly after that.

Cheers,
Dani

	it("shouldnt be possible to delete another Person", async function() {
		let instance = await People.deployed();
		await instance.addPerson("Bob", 66, 187, {from: accounts[0], value: 1000});
		//await instance.deletePerson(accounts[0]);
		await truffleAssert.fails(instance.deletePerson(accounts[1],{from: accounts[1]}), truffleAssert.ErrorType.REVERT);
	});
	it("should be possible to delete a Person as owner", async function() {
		let instance = await People.deployed();
		await instance.addPerson("Bob", 66, 187, {from: accounts[2], value: 1000});
		await truffleAssert.passes(instance.deletePerson(accounts[2], {from: accounts[0]}));
	});

Thank you, it worked. I hadn’t installed it in the root directory, just my project

1 Like

@filip
I’m having trouble handling big numbers or subtracting them in javascript.
What is the proper way to deal with this? I tried playing around with BN from bn.js, but with no success yet.

My Assertion fails because of this.

Example:

	it("should be able to withdraw as the owner", async function() {
		
		await instance.addPerson("Bob", 66, 187, {from: accounts[2], value: 10000});
		await instance.addPerson("Bob", 66, 187, {from: accounts[1], value: 1000});
		let b_owner = parseFloat(await web3.eth.getBalance(accounts[0]));
		let b_holdings = await instance.getHoldings();
		await instance.withdrawAll();
		let a_holdings = await instance.getHoldings();
		let a_owner = parseFloat(await web3.eth.getBalance(accounts[0]));
		console.log("RESULTS:");
		console.log("CON: " + b_holdings);
		console.log("OWNER: " + b_owner);		
		console.log("AFTER:");
		console.log("CON: " + a_holdings);
		console.log("OWNER: " + a_owner);
		console.log("DIFF: " + (a_owner - b_owner));
		assert(a_holdings == 0 && a_owner > b_owner);

Console Log:

RESULTS:
CON: 11000
OWNER: 84712085574000150000
AFTER:
CON: 0
OWNER: 84711658734000160000
DIFF: -426839999987712

That

parseFloat()

part was tricky

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

contract("People", async function(accounts){
  let instance;

  before(async function(){
    instance = await People.deployed()
  });

  it("shouldnt create with age over 150 years", async function(){
    await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);

  });
  it("shouldnt create a person without payment", async function(){
    await truffleAssert.fails(instance.createPerson("Bob", 50, 190, {value: 1000}), truffleAssert.ErrorType.REVERT);
  });
  it("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("bobs age is correct", async function(){
    let result = await instance.getPerson();
    assert(result.age.toNumber() === 65, "Age not set correctly");
  });
  it("should not allow non owner delete perosn", async function(){
    await instance.createPerson("Zala", 25, 180, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.fails(instance.deletePerson(accounts[2], {from: accounts[2]}), truffleAssert.ErrorType.REVERT);
  });
  it("should allow owner to delete person", async function(){
    let instance = await People.new();
    await instance.createPerson("Zala", 25, 180, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.passes(accounts[2], {from: accounts[0]});
  });
  it("can withdraw ballance", async function(){
    let instance = await People.new();
    await instance.createPerson("ZAN", 25, 170, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
  });
  it("the contract has balance", async function(){
    let instance = await People.new();
    await instance.createPerson("ZAN", 25, 170, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    let contBalance = parseFloat(await web3.eth.getBalance(accounts[0]));
    assert(contBalance > 0, "YES");
  });
  it("contract balance 0 after withdraw", async function(){
    let instance = await People.new();
    let contOldBalance = parseFloat(await web3.eth.getBalance(accounts[0]));
    await instance.createPerson("ZAN", 25, 170, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
    await instance.withdrawAll({from: accounts[0]});
    let contNewBalance = parseFloat(await web3.eth.getBalance(accounts[0]));
    assert(contOldBalance < contNewBalance, "YES");
  });
});

1 Like

const People = artifacts.require(“People”);
const truffleAssert= require(“truffle-assertions”);
contract(“People”, async function(accounts){
it(“Only owner can access creator account”, async function(){
let instance= await People.deployed();
let result= await instance.getCreator(0);
assert(result===accounts[0],“User is not the owner”)
});
it(“Should only be able to delete by owner!”,async function(){
let instance= await People.deployed();
await instance.createPerson(“Ralph”, 28, 170, {value: web3.utils.toWei(“1”,“ether”), from: accounts[1]});
await instance.getPerson();
await truffleAssert.fails(instance.deletePerson(accounts[1],{from:accounts[1]}), truffleAssert.ErrorType.Revert
);
});
it(“Should only be withdraw by the owner”, async function(){
let instance= await People.deployed();
await instance.createPerson(“Mana”, 45, 165,{value: web3.utils.toWei(“1”,“ether”), from: accounts[2]})
await truffleAssert.fails(instance.withdrawAll({from: accounts[2]}),truffleAssert.ErrorType.Revert);
await instance.withdrawAll();
});
});

// people_test.js
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function(accounts){
  it("shouldn't be able to delete a person by other than the owner", async function(){
    let instance = await People.deployed();
    let owner = await instance.owner();
    let otherAccount = accounts[2];
    assert(otherAccount !== owner, 
      "ASSERT: OTHER TEST ACCOUNT MAY NOT BE THE OWNER!");
    await instance.createPerson(
      "Dora", 33, 177, {from: otherAccount, value: web3.utils.toWei("1", "wei")}
    );
    await truffleAssert.fails(
      instance.deletePerson(otherAccount, {from: otherAccount}),
      truffleAssert.ErrorType.REVERT, null,
      "ASSERT: OTHER TEST ACCOUNT MY CALL deletePerson() !"
    );
    assert(otherAccount !== owner, 
      "ASSERT: OTHER TEST ACCOUNT MAY NOT BE THE OWNER!");
  })
  it("should be able to delete a person by the owner", async function(){
    let instance = await People.deployed();
    let owner = await instance.owner();
    let otherAccount = accounts[1];
    assert(otherAccount !== owner, 
      "ASSERT: OTHER TEST ACCOUNT MAY NOT BE THE OWNER!");
    await instance.createPerson(
      "Carla", 66, 166, {from: otherAccount, value: web3.utils.toWei("1", "wei")}
    );
    await truffleAssert.passes(
      instance.deletePerson(otherAccount, {from: owner}),
      truffleAssert.ErrorType.REVERT, null,
      "ASSERT: OWNER ACCOUNT CANNOT CALL deletePerson() !"
    );
  })
});

Value Test Assignment

// people_test.js
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function(accounts){
  let instance, cost, owner, contractAddress, accountAddress;
  beforeEach(async function(){
    instance = await People.new();
    cost = Number(web3.utils.toWei("1", "gwei"));
    owner = await instance.owner();
    contractAddress = instance.address;
    accountAddress = accounts[1];
  });
  it("The call of withdrawalAll() should be not possible by non-owners", async function(){
    await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    await truffleAssert.fails(
      instance.withdrawAll({from: accountAddress}),
      truffleAssert.ErrorType.REVERT,
      null,
      "ASSERT: Contract did not revert!"
    );
  })
  it("The call of withdrawalAll() should be possible by the owner", async function(){
    await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    await truffleAssert.passes(
      instance.withdrawAll({from: owner}),
      truffleAssert.ErrorType.REVERT,
      null,
      "ASSERT: Contract did revert although it was the owner!"
    );
  })
  it("After withdrawalAll() the balance of contract should be 0", async function(){
    let contractBalanceBeforeTrx = Number(await web3.eth.getBalance(contractAddress));
    await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    await instance.withdrawAll({from: owner});
    let balanceFromBlockChainAfter = Number(await web3.eth.getBalance(instance.address));
    let balanceFromMethodAfter = Number(await instance.balance());
    assert(balanceFromBlockChainAfter === 0,
      "ASSERT: Contract balance from blockchain is not 0 after withdrawalAll() ! \r\n"+
      `${balanceFromBlockChainAfter} !== 0 `
    );
    assert(balanceFromMethodAfter === 0,
      "ASSERT: Contract balance from balance() is not 0 after withdrawalAll() ! \r\n"+
      `${balanceFromMethodAfter} !== 0`
    );
    assert(balanceFromMethodAfter === balanceFromBlockChainAfter,
      `ASSERT: Contract balance from balance() is not equal to balance from blockchain !`);
  })
  it("After createPerson() the balance of contract should increase by value send", async function(){
    let contractBalanceBeforeTrx = Number(await web3.eth.getBalance(contractAddress));
    await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    let contractBalanceAfterTrx = Number(await web3.eth.getBalance(contractAddress));
    let contractBalanceExpectedAfterTrx = contractBalanceBeforeTrx + cost;
    assert(contractBalanceExpectedAfterTrx === contractBalanceAfterTrx,
      "ASSERT: Contract balance from blockchain has not been increased! "+
      `${contractBalanceAfterTrx} - ${cost} - ${contractBalanceBeforeTrx} === ${(contractBalanceAfterTrx + cost - contractBalanceBeforeTrx)}`);
  })
  it("After createPerson() the account balance should increase", async function(){
    let accountBalanceBeforeTrx = Number(await web3.eth.getBalance(accountAddress));
    await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    let accountBalanceAfterTrx = Number(await web3.eth.getBalance(accountAddress));
    assert(accountBalanceBeforeTrx > accountBalanceAfterTrx,
      "ASSERT: Account balance has not been decreased!");
  })
  it("After createPerson() the account balance should increase by value send and by gas cost", async function(){
    let accountBalanceBeforeTrx = Number(await web3.eth.getBalance(accountAddress));
    const txInfo = await instance.createPerson("Carla", 66, 166, {from: accountAddress, value: cost});
    const tx = await web3.eth.getTransaction(txInfo.tx);
    let gasCost = Number(tx.gasPrice) * Number(txInfo.receipt.gasUsed);
    let accountBalanceAfterTrx = Number(await web3.eth.getBalance(accountAddress));
    let accountBalanceExpectedAfterTrx = accountBalanceBeforeTrx - cost - gasCost;
    let accountBalanceDifferenceAfterTrx = accountBalanceExpectedAfterTrx - accountBalanceAfterTrx;
    // the accountBalanceDifferenceAfterTrx is sometimes not exactly 0 wei
    // assert(accountBalanceDifferenceAfterTrx === 0,
    assert(-10000 <= accountBalanceDifferenceAfterTrx && accountBalanceDifferenceAfterTrx <= 10000,
        "ASSERT: Account balance has not been decreased by cost!");
  })
});

The value of accountBalanceDifferenceAfterTrx in the last test is not 0 for all the test runs, as it sometimes differs in a small 4 digit number of wei. I am not quite sure why. Couls it be because aof a rounding error?

For some reason truffle doesnt try to use the correct compiler version, even though I specified in the truffle-config.js file:

How can I fix this?

Restarting the console somehow magically fixed the problem…

1 Like

If you run ganache and then you change the truffle version in truffle-config, then you have to restart the console so that it loads the right compiler version :slight_smile: