Hi @JRB
As we can see in your test, the user creation is not failing. It means your require is not working in the createPerson method. Are you checking the age submitted in your smart contract ?
If yes can you share this function code with us ?
Thx
Hi @kiddey
There is a typo in your first test:
await instance.createPerson(āDaveā, 80, 140, {value: web3.utils.toWei(ā1ā, āetherā), from accounts[1]});
Should be
await instance.createPerson(āDaveā, 80, 140, {value: web3.utils.toWei(ā1ā, āetherā), from: accounts[1]});
How do you make your second test working ? Where is you instance declared ? You are using the deletePerson method on instance but i this you should add
let instance = await People.deployed();
At the beginning of your test 2, 4 and 5. Did you use a āBeforeEachā function at the beginning of your test file ?
Hi @ToMMaaY
Your tests are correct, but it is better to test your functionalities one by one before testing multiples functions in one test. As you are using ābeforeEachā People.deployed you can split your first test into 2 tests. Your first test is called āshould be able to delete personā but it could fail creating one ,so it will be a bit confusing for someone else running your test if the error come from createPerson.
Hi, here are my tests for checking the balance:
it("Balances should be matching after creating a person", async function() {
let instance = await People.new();
await instance.createPerson("Brook", 65, 280, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
let expectedBalance = await instance.balance();
let actualBalance = await web3.eth.getBalance(instance.address);
assert.equal(actualBalance, expectedBalance);
});
it("Owner is able to withdraw", async function() {
await instance.createPerson("Brook", 65, 280, {value: web3.utils.toWei("1",'ether')});
await truffleAssert.passes(instance.withdrawAll({from: accounts[0]}),"Owner can't withdraw");
});
it("Owner should be able to withdraw balance and the balance should be 0", async function() {
let instance = await People.new();
await instance.withdrawAll();
let expectedBalance = await instance.balance();
let actualBalance = await web3.eth.getBalance(instance.address);
assert.equal(actualBalance, expectedBalance);
});
Hi @gabba!
Here is the create person function code.
function createPerson(string memory name, uint age, uint height) public payable costs(1 ether){
require(age > 200, "Age needs to be below 200");
require(msg.value >= 1 ether);
balance += msg.value;
I have swiched the require age from 150 to 200, and then the age test passed. However the senior test still fails. Allso please tell me if I wassenāt supossed to change the require statment.
Here is the people.sol contract if you need more information.
import "./Ownable.sol";
pragma solidity 0.5.12;
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 > 200, "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;
}
}
Owner Test Assignment
Unit Testing
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract( "People", async function( accounts){
it("should not allow a non-creator/owner of the person entry to delete the person", async function(){
let instance = await People.deployed();
await instance.createPerson( "Rossi", 22, 160, { value: web3.utils.toWei("1", "ether"), from: accounts[3] });
await truffleAssert.fails( instance.deletePerson( accounts[3], { from: accounts[3]} ), truffleAssert.ErrorType.REVERT);
});
it("should allow the creator/owner of the person entry to delete the person", async function(){
let instance = await People.deployed();
await instance.createPerson( "Valentino", 39, 160, { value: web3.utils.toWei("1", "ether"), from: accounts[2] });
await truffleAssert.passes( instance.deletePerson( accounts[2], { from: accounts[0]}));
});
});
Edited by @gabba: please use the Preformatted text tag t post code @ibin
Those of you getting the peopleproject migration error from starting a new project need to go into their js config in the new folder, remove the comment for the sol version, and add 0.5.12 like in the first few videos. I am sure most of you already figured this out.
Hi @JRB
Your require should check if the age is inferior to 200 and not superior to 200.
require(age < 150, "Age needs to be below 150");
You are using the wrong operator <
So i think you are not creating a new user and at the end the value of newPerson.senior is false because the default value of a boolean if itās not set is false.
Using the correct require should solve you issue
Thanks. It finlaly worked. Thank you so much for your help!
Here is my code:
it ("should delete user if you are onlyOwner", async function(){
let instance = await People.deployed();
await instance.createPerson("June", 65, 190, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.passes(instance.deletePerson(accounts[1], {from: accounts[0]}), truffleAssert.ErrorType.REVERT);
let result = await instance.getPerson();
});
it ("should not delete user if you are not onlyOwner", async function(){
let instance = await People.deployed();
await instance.createPerson("June", 65, 190, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.deletePerson(accounts[2], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
let result = await instance.getPerson();
})
Edit by gabba: plz use the preformatted text tag thx you @DeCryptolorian
More answers - I was so close without parseFloatā¦
it ("balance should increase when a person is added", async function(){
let instance = await People.new();
await truffleAssert.passes(instance.createPerson("Jim", 20, 190, {value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
let c_balance = await instance.balance();
let a_balance = await web3.eth.getBalance(instance.address);
assert(c_balance == a_balance);
});
it ("balance cannot be withdrawn by another", async function(){
let instance = await People.new();
await truffleAssert.passes(instance.createPerson("Blue", 20, 190, {from: accounts[2], value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
await truffleAssert.fails(instance.withdrawAll({from: accounts[2]}), truffleAssert.ErrorType.REVERT);
});
it ("balance can be withdrawn by onlyOwner", async function(){
let instance = await People.new();
await truffleAssert.passes(instance.createPerson("Green", 20, 190, {from: accounts[2], value: web3.utils.toWei("1", "ether")}), truffleAssert.ErrorType.REVERT);
await instance.withdrawAll({from: accounts[0]});
});
it ("balance increases for onlyOwner and contract balance is 0", async function(){
let instance = await People.new();
await instance.createPerson("Lisa", 35, 160, {from: accounts[2], value: web3.utils.toWei("1", "ether")});
let o_before_balance = parseFloat(await web3.eth.getBalance(accounts[0]));
await instance.withdrawAll();
let o_after_balance = parseFloat(await web3.eth.getBalance(accounts[0]));
assert(o_before_balance < o_after_balance, "Owners balance was updated");
});
Edit by gabba: plz use the preformatted text tag thx you @DeCryptolorian
const People = artifacts.require("People");
const truffleAssert = require('truffle-assertions');
contract("People", async accounts => {
it('should not allow non-owner deletions', async () => {
const instance = await People.deployed();
truffleAssert.fails(
instance.deletePerson(accounts[0], { from: accounts[1] }),
truffleAssert.ErrorType.REVERT
);
});
it('should allow owner to delete', async () => {
const instance = await People.deployed();
truffleAssert.passes(instance.deletePerson(accounts[0], { from: accounts[0] }));
});
});
const People = artifacts.require("People");
const truffleAssert = require('truffle-assertions');
contract("People", async accounts => {
let instance;
beforeEach(async () => {
instance = await People.new();
});
it('should have correct balance after creating a person and owner withdraws', async () => {
await instance.createPerson('Bob', 65, 4, { value: web3.utils.toWei('1.5', 'ether') });
let internalBalance = await instance.balance();
let actualBalance = web3.utils.toBN(await web3.eth.getBalance(instance.address));
assert.deepEqual(internalBalance, actualBalance);
assert.deepEqual(web3.utils.toBN(web3.utils.toWei('1.5', 'ether')), actualBalance);
await instance.withdrawAll();
internalBalance = await instance.balance();
actualBalance = web3.utils.toBN(await web3.eth.getBalance(instance.address));
assert.deepEqual(internalBalance, actualBalance);
assert.deepEqual(web3.utils.toBN(web3.utils.toWei('0', 'ether')), actualBalance);
});
});
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function(accounts) {
it("Should remove person if deletePerson is executed by owner", async function(){
let instance = await People.deployed();
let ownerAddress = accounts[0];
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});
instance.deletePerson(ownerAddress);
let result = await instance.getPerson();
assert(result.age.toNumber() == 0, "Person not correctly deleted");
});
it("Shouldn't remove person if deletePerson not executed by owner", async function(){
let instance = await People.deployed();
let ownerAddress = accounts[0];
let notOwnerAddress = accounts[1];
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.deletePerson(ownerAddress, {from: notOwnerAddress}), truffleAssert.ErrorType.REVERT);
});
});
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
contract("People", async function(accounts) {
let instance;
//run before all tests
before(async function(){
instance = await People.deployed();
});
it("Should increase balance by 1 ether when creating a person", async function(){
let contractAddress = instance.address;
let notOwnerAddress = accounts[3];
let initialBalance = await web3.eth.getBalance(contractAddress)
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether"), from: notOwnerAddress});
let finalBalance = await web3.eth.getBalance(contractAddress)
assert((finalBalance - initialBalance) == web3.utils.toWei("1", "ether"));
});
it("Shouldn't allow withdraw to non owner", async function(){
let contractAddress = instance.address;
let notOwnerAddress = accounts[3];
await truffleAssert.fails(instance.withdrawAll({from: notOwnerAddress}), truffleAssert.ErrorType.REVERT);
});
it("Should allow withdraw to owner", async function(){
await truffleAssert.passes(instance.withdrawAll());
});
it("Should hold zero balance after withdraw", async function(){
let contractAddress = instance.address;
let ownerAddress = accounts[0];
let notOwnerAddress = accounts[3];
await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether"), from: notOwnerAddress});
let contractAddressBalance = await web3.eth.getBalance(contractAddress);
let contractInitialBalance = contractAddressBalance;
console.log("contractAddressBalance: ", contractAddressBalance);
assert(contractAddressBalance > 0, "Contract balance should be greater than zero");
await instance.withdrawAll();
let floatBalance = await instance.balance();
let contractBalance = parseFloat(floatBalance);
contractAddressBalance = await web3.eth.getBalance(contractAddress);
assert(contractBalance == 0, "Contract instance balance is not zero after withdraw");
assert(contractAddressBalance == 0, "Contract address balance is not zero after withdraw");
});
it("Should transfer balance to owner", async function(){
let contractAddress = instance.address;
let ownerAddress = accounts[0];
let notOwnerAddress = accounts[3];
let ownerAddressBalance = await web3.eth.getBalance(ownerAddress);
let ownerAddressInitialBalance = ownerAddressBalance;
console.log("Contract owner balance is: ", ownerAddressBalance);
const txReceipt = await instance.createPerson("Bob", 65, 190, {value: web3.utils.toWei("1", "ether"), from: notOwnerAddress});
const gasFee = txReceipt.receipt.gasUsed;
console.log("gasFee: ", gasFee);
let contractBalance = await web3.eth.getBalance(contractAddress);
let contractInitialBalance = contractBalance;
console.log("contractBalance: ", contractBalance);
assert(contractBalance > 0, "Contract balance should be greater than zero");
await instance.withdrawAll();
ownerAddressBalance = await web3.eth.getBalance(ownerAddress);
console.log("Contract owner balance is: ", ownerAddressBalance);
assert(ownerAddressBalance > ownerAddressInitialBalance, "Ower funds are not correct after withdraw.");
//console.log(ownerAddressInitialBalance + contractInitialBalance - gasFee);
//assert(ownerAddressBalance == (ownerAddressInitialBalance + contractInitialBalance - gasFee), "Owner funds are not correct after withdraw.");
});
});
Hey @filip, @gabba!
In the Owner Test Asinment I have the test that makes sure that if a user is not owner of a person and atempts to delet that person it will fail, that test is allmost complete. However I have one problem that I just canāt figure out. When I run the test the following errer occures:
As you can see, it explains that accounts is not difined.
As much as I tried I canāt seem to fix this problem.
Here is the peopletest.js file.
const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");
// This test makes shore that a person isent created with an age of over 150 years
contract("People", async function(){
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);
});
// This test makes shore that a person isent ceated without payment
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);
});
// This test makes shore that the senior of a person is set correctly
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");
});
// This test makes shore that the age of a person is set correctly
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");
});
// This test makes shore that only the owner of a person can delete his person
it("Delete Unseccesfull, User is not owner of person.", async function(){
let instance = await People.deployed();
await instance.createPerson("Timmy Fias", 65, 6, {value: web3.utils.toWei("1", "ether")});
await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
});
Let me know if you need any more information.
Thanks!
Hey @DeCryptolorian!
If you use preformated text to show your code than it will be easier to read. As is, reading your code is sort of dificult to understand.
onlyOwner Test:
contract("People", async (accounts) => {
let instance;
beforeEach(async () => {
instance = await People.deployed();
})
it("should delete person when you're owner", async () => {
await instance.deletePerson(accounts[0], { from: accounts[0]} )
let result = await instance.getPerson();
assert(result.age.toNumber() === 0, "Person not deleted")
})
it("shouldn't delete when you're not owner", async () => {
await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}), truffleAssert.ErrorType.REVERT)
})
})
Never mind. I remembered that I can define something in the peramiters of a function.
That test passed.
On to the next one!
Here is my solotion for the Owner Test Asinment.
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");
});
// This test makes shore that only the owner of a person can delete his person
it("Delete Unseccesfull, User is not owner of person.", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
});
// This test makes shore that the owner can delet his person.
it("Should let owner of person delet his person", async function(){
let instance = await People.deployed();
await (instance.deletePerson(accounts[0], {from: accounts[0]}));
});
});