// SECOND ASSIGNMENT ON TESTS WITH TRUFFLE AND ASSERTIONS
// VERIFYING PAYMENTS
contract("People", async function(accounts){
let instance;
let contractBalance;
let ownerBalance;
let senderBalance;
let ownBalBeforeWithdrawal;
let ownBalAfterWithdrawal;
before(async function(){
instance = await People.new();
ownerBalance = await web3.eth.getBalance(accounts[0]);
senderBalance = await web3.eth.getBalance(accounts[3]);
});
it("should initialize with contract's balance in 0 Wei", async function(){
contractBalance = await web3.eth.getBalance(instance.address);;
assert(parseInt(contractBalance) === 0,
"Contract's balance is different from 0 Wei right after deployment");
})
it("should increase contract balance in 1 ether after adding a person", async function(){
await instance.createPerson("Lucy", 22, 180, {value: web3.utils.toWei("1", "ether")});
contractBalance = await web3.eth.getBalance(instance.address);
assert(parseInt(contractBalance) === parseInt(web3.utils.toWei("1", "ether")), // 1000000000000000000,
"Contract's balance has not been credited 1 ether after adding a person");
});
it("should keep the exact same balance in internal variable balance as in contract's balance", async function(){
let internalBalance = await instance.balance();
assert(parseInt(internalBalance) === parseInt(contractBalance),
"Internal variable balance is not equal to contract's balance");
});
it("should revert attemp by non-owner to withdrawal funds from contract's balance", async function(){
await truffleAssert.fails(instance.withdrawAll({from: accounts[3]}), truffleAssert.ErrorType.REVERT);
});
it("should keep contract balances in 1 ether after failed withdrawal attempt", async function(){
contractBalance = await web3.eth.getBalance(instance.address);
let internalBalance = await instance.balance();
assert(parseInt(contractBalance) === parseInt(web3.utils.toWei("1", "ether")) &&
parseInt(internalBalance) === parseInt(web3.utils.toWei("1", "ether")),
"Balances in contract have changed after non-owner's withdrawal attempt");
});
it("should allow the owner to withdraw funds from contract's balance", async function(){
ownBalBeforeWithdrawal = await web3.eth.getBalance(accounts[0]);
await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}));
});
it("should have reseted contract balances to zero after owner full withdrawal", async function(){
contractBalance = await web3.eth.getBalance(instance.address);
let internalBalance = await instance.balance();
assert(parseInt(contractBalance) === 0 &&
parseInt(internalBalance) === 0,
"Balances in contract have not been reseted after owner's withdrawal");
});
it("should have increased owner's balance after withdrawal from contract", async function(){
ownBalAfterWithdrawal = await web3.eth.getBalance(accounts[0]);
assert(parseInt(ownBalAfterWithdrawal) > parseInt(ownBalBeforeWithdrawal),
"Owner's balance has not increased after withdrawal from contract");
});
});
Okay, so I just watched the âOwner Test Assignment Solutionâ video, because I couldnât figure it out on my own, mostly because I didnât know about the concept of using âaccountsâ. But my first thought when I was planing this assignment was to use msg.sender = owner function, as that made most sence to me, we would just include the Ownable.sol file on the top of the peopletest.js file and that way test if the address of the person who deletes people matches with the owner. But when I constructed that test function I got an error (msg.sender not defined), even tho I linked everything correctly and made a ownable migration file etc.
So my question is, why did it not work? And if it could work somehow, would it be simpler than writing 2 tests? It would kill 2 birds with 1 stone, right?
As you are using a lot of variable to track the current state of your contract, i donât think you need to deploy a new instance for each test.
before(async function(){
instance = await People.new();
ownerBalance = await web3.eth.getBalance(accounts[0]);
senderBalance = await web3.eth.getBalance(accounts[3]);
});
This will execute this action before each test âitâ .
But by the way you have designed your test you can just initialize your instance in the first test.
Your tests will cost less to executes than creating a new instance for each test.
Hi @Djuzy_J
Your People contract is already inheriting from the ownable contract you donât have to import it in the test.
But default an array of accounts are inject by the truffle framework, also by default the first account of this array will be used to deploy the contract, so accounts[0] will be the owner of the contract.
So at the beginning of your test file you just have to declare a variable owner = accounts[0] if you want to use it later.
If you want to change it read my previous post
https://forumtest.ivanontech.com/t/unit-testing-in-truffle/10053/189
In your test msg.sender is not defined because you are mixing .sol and .js files which are not using the same language.
msg
is an object available in your smart contract methods not in a javascript file.
If you still have issues can you share your test with us ?
@gabba Man, thank you for this check
There is one thing I still do not understand well. I think I misunderstood how the before() function works. I thought that if I instantiated " instance = await People.new(); " inside the BEFORE function, the instance would be created only once before all the âitâ tests. With this code, am I creating a new instance in each âitâ ???
before(async function(){
instance = await People.new();
...
}
This is not my intention !! On purpose, I had not used a beforeEach() in order to avoid that. But, I guess I am not understanding well how to use the before() function⌠Should I declare and instantiate like this --> let instance = await People.new() before using the before() function ???
Man, I appreciate all the help
Oups my bad ahaha i though you used beforeEach apologies @Glenn_CostaRica I donât know why i was sure it was beforeEach
@gabba Mannn, thanks a lot This happens to me ALL THE TIME !! Iâm a university professor, and I need to apologize so frequently to my students !!! Canât keep track of every detail sometimes⌠Man, I love how dedicated you, guys, are! You read each homework, each detail! You give comments and directions to each student!! This Academy is amazing Love from Costa Rica
Hey
when i try to run the test in Truffle I get this error, anyone know how to solve this? In my attempt to solve this problem I did copy @filip s code from github, so my code should be ok or? I can read something about this issue might can be due to the version 12 of node, should/could i change it to version 10 or would it mess it up?
Rather try than copy aka. rookie of the year:
it(âShould be owner that delete personâ, async function(){
let instance = await People.deployed();
await instance.deletePerson(accounts[0], {value: web3.utils.toWei(â1â, âetherâ)});
let result = await instance.getPerson(accounts[0]);
assert(result.accounts[0] === onlyOwner, âWrong person tried to delete, needs to be ownerâ);
});
Hi @Jacob_M
Yes you need to use node 10 install it with nvm itâs easier
otherwise you can check this post
https://forumtest.ivanontech.com/t/introduction-to-unit-testing/10052/42
Owner test:
contract("PeopleAccnt1", async function(accounts) {
it ("should create person", async function() {
let instance = await People.deployed();
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "finney"), from: accounts[0]});
let result = await instance.getPerson();
assert(result.age.toNumber() === 65, "Age was not set correctly");
});
});
contract("PeopleAccnt2", async function(accounts) {
it ("shouldn't delete person", async function() {
let instance = await People.deployed();
await truffleAssert.fails(instance.deletePerson(accounts[1], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
});
hey @filip i am getting following error
Using network âganacheâ.
Compiling your contractsâŚ
Compiling .\contracts\Migrations.sol
Compiling .\contracts\Ownable.sol
Compiling .\contracts\People.sol
Artifacts written to C:\Users\gandh\AppData\Local\Temp\test-2020425-19132-1h3o3su.gzdd
Compiled successfully using:
- solc: 0.5.12+commit.7709ece9.Emscripten.clang
Contract: People
1) shouldât create a person with age over 150 years
> No events were emitted
2) shouldnât create a person without payment
> No events were emitted
3) should set senior status correctly
> No events were emitted
0 passing (180ms)
3 failing
-
Contract: People
shouldât create a person with age over 150 years:
AssertionError: Expected to fail with [object Object], but failed with: Error: Returned error: VM Exception while processing transaction: revert
at fails (node_modules\truffle-assertions\index.js:152:13)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at Context. (test\peopletest.js:7:5) -
Contract: People
shouldnât create a person without payment:
ReferenceError: instance is not defined
at Context. (test\peopletest.js:10:31)
at processTicksAndRejections (internal/process/task_queues.js:97:5) -
Contract: People
should set senior status correctly:
ReferenceError: instance is not defined
at Context. (test\peopletest.js:13:5)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
3
Hi @Gandharv_dalal can you share your test file with us ?
those errors are pretty straightforward
1 - AssertionError: Expected to fail with [object Object], but failed with: Error: Returned error: VM
You are using an object in you assert instead of an error code.
2/3 - ReferenceError: instance is not defined
instance is not defined -> it means that instance.createPeople canât be called because instance doesnât exist. How are you deploying your instance ? Are you doing the same thing as in the video ?
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function (accounts)
{
it("Should not 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("Should not create a person without payment", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.createPerson("Alice",23,200,{value: "1000" }), truffleAssert.ErrorType.REVERT);
});
it("Should set senior status correctly", 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("Should not allow users other than the owner to delete and should delete correctly when owner deletes", async function(){
let instance = await People.deployed();
let owner = accounts[0];
let user1 = accounts[1];
let user2 = accounts[2];
await instance.createPerson("Bob",65,190, {value: web3.utils.toWei("1", "ether"), from:user1});
await instance.createPerson("Alice",25,150, {value: web3.utils.toWei("1", "ether"), from: user2});
await truffleAssert.fails(instance.deletePerson(user2,{from: user1}), truffleAssert.ErrorType.REVERT);
await instance.deletePerson(user2,{from:owner});
let result = await instance.getPerson({from:user2});
assert(result.age.toNumber()===0, "Age not set correctly when owner deletes");
});
});
Combined the test into one test. It is the last âitâ command.
Please let me know if this is good/accurate.
Thank you!
Value Assignment Solution
it("Should allow only the owner to withdraw", async function(){
let instance = await People.deployed();
let owner = accounts[0];
let user1 = accounts[1];
let user2 = accounts[2];
await truffleAssert.fails(instance.withdrawAll({from: user1}), truffleAssert.ErrorType.REVERT);
});
it("Should update the contract balance to 0 after withdrawing", async function(){
let instance = await People.new();
let owner = accounts[0];
let user1 = accounts[1];
let user2 = accounts[2];
await instance.createPerson("Bob",65,190, {value: web3.utils.toWei("1", "ether"), from: user1});
await instance.createPerson("Alice",25,150, {value: web3.utils.toWei("1", "ether"), from: user2});
await instance.withdrawAll();
let newBalance = await instance.balance();
newBalance = parseFloat(newBalance);
assert(newBalance == 0, "Post withdrawal balance is incorrect");
});
it("Should allow the owner to withdraw from contract", async function(){
let instance = await People.new();
let owner = accounts[0];
let user1 = accounts[1];
let user2 = accounts[2];
await instance.createPerson("Bob",65,190, {value: web3.utils.toWei("1", "ether"), from: user1});
await instance.createPerson("Alice",25,150, {value: web3.utils.toWei("1", "ether"), from: user2});
await truffleAssert.passes(instance.withdrawAll({from:owner}));
});
it("Should update the owner's balance after a successful withdrawal", async function(){
let instance = await People.new();
let owner = accounts[0];
let user1 = accounts[1];
let user2 = accounts[2];
let oldBalance = parseFloat(await web3.eth.getBalance(accounts[0]));
await instance.createPerson("Bob",65,190, {value: web3.utils.toWei("1", "ether"), from: user1});
await instance.createPerson("Alice",25,150, {value: web3.utils.toWei("1", "ether"), from: user2});
await instance.withdrawAll();
let newBalance = parseFloat(await web3.eth.getBalance(accounts[0]));
assert(oldBalance < newBalance , "New balance is not greater than the old balance");
});
it("Should set owner correctly", async function(){
let instance = await People.deployed();
let result = await instance.owner.call();
assert(result == accounts[0], "Owner was not set correctly");
});
it("Should allow owner to call owner-only functions", async function(){
let instance = await People.deployed();
await truffleAssert.passes(
instance.getCreator(0)
);
});
it("Should not allow normal users to call owner-only functions", async function(){
let instance = await People.deployed();
await truffleAssert.fails(
instance.getCreator(0, {from: accounts[1]}),
truffleAssert.ErrorType.REVERT
);
});
it("Should add funds to balance correctly", async function(){
let transactionValue = web3.utils.toWei("2", "Ether");
await instance.createPerson(
"Bob",
20,
180,
{value:transactionValue, from: accounts[1]}
);
let contractBalance = await web3.eth.getBalance(instance.address);
let internalBalance = await instance.balance();
assert(contractBalance == internalBalance, "contract balance is wrong");
});
it("Should update contract balance to 0 after withdrawing", async function(){
await instance.withdrawAll();
let newBalance = await instance.balance.call();
assert(newBalance == 0, "contract balance after withdrawl is wrong");
});
Hi @anton6
How do you know that this test is correct ?
it("Should add funds to balance correctly", async function(){
let transactionValue = web3.utils.toWei("2", "Ether");
await instance.createPerson(
"Bob",
20,
180,
{value:transactionValue, from: accounts[1]}
);
let contractBalance = await web3.eth.getBalance(instance.address);
let internalBalance = await instance.balance();
assert(contractBalance == internalBalance, "contract balance is wrong");
});
If no funds are sent to you contract
0 === 0 will succeed
You are not checking that 2 ETH have been sent
Thank you!
const People = artifacts.require(âPeopleâ);
const truffleAssert = require(âtruffle-assertionsâ);
contract(âOwnableâ, async function(accounts){
it(âShould only delete if ownerâ, async function() {
let instance = await People.deployed();
//create a person with the first account
await instance.createPerson("edson", 123, 180, {value: web3.utils.toWei("1", "ether"), from: accounts[0]});
//try to delete first account, with second account. Shouldn't be allowed
await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
it("Should delete if owner", async function() {
let instance = await People.deployed();
//Delete person created above by using first account which is owner.
await truffleAssert.passes(instance.deletePerson(accounts[0], {from: accounts[0]}));
})
})