Trang chủ Tạp chí Lập trình smart contract: Phần 5 — Viết test case cho smart contracts

Lập trình smart contract: Phần 5 — Viết test case cho smart contracts

Tiếp tục loạt bài thực tế phát triển dApp, giờ chúng ta sẽ nâng độ khó lên một chút xíu khi đi vào hoàn thiện nội dung của smart contracts và viết test case kiểm thử.

Smart contracts

Events

Các smart contracts được thực thi trong môi trường của EVM, hoàn toàn tách biệt với môi trường bên ngoài. Để có thể trigger một sự kiệu ra bên ngoài EVM ta gửi các events được định nghĩa trước:

//New job append
 event NewJob(
 uint256 indexed id,
 address creator,
 uint256 salary,
 uint256 timeOut);

//An woker start working
 event TakeJob(
 uint256 indexed id,
 address indexed labor);

Các event này có thể lắng nghe thông qua các filter cung cấp bởi web3js, việc này sẽ cung cấp thêm thông tin, trigger các hệ thống third party hoặc đơn giản là điều chỉnh lại front-end.

Modifier

Để smart contract của mình bảo mật hơn, mình thêm các modifier. Mục tiêu là kiểm tra arguments trước khi method được trigger (Ethereum là một hệ hoàn toàn thụ động, không có khả năng tự tính toán).

//Transaction must contant Ethereum
 modifier onlyHaveFund {
 require(msg.value > MINIUM_SALARY);
 _;
 }

Trên đây bạn có thể đọc thấy modifier rất rõ nghĩa, với modifier này mình check số Ethereum có trong transaction. Biến msg sẽ chứa vài thông tin hữu ích của transaction (eg. msg.sender: address của người gửi, msg.value: số ethereum tính bằng wei). Để biết rõ thêm global variable các bạn xem ở đây.

Smart contract

Mình viết lại smart contract, thêm hai function mới takeJob() và viewJob():

//Take job

function

takeJob (uint256 jobId)

public onlyValidMortgage(jobId) onlyValidId(jobId) onlyValidJob(jobId)

{

//Trigger event to log labor

TakeJob(jobId, msg.sender);



//Change working state

jobData[jobId].start = block.timestamp;

}



//Veiw job data

function

viewJob(uint256 jobId)

public onlyValidId(jobId) constant returns (

uint256 id,

address creator,

uint256 salary,

uint256 start,

uint256 end,

uint256 timeOut,

bytes title,

bytes description)

{

Job memory jobReader = jobData[jobId];

return (jobReader.id,

jobReader.creator,

jobReader.salary,

jobReader.start,

jobReader.end,

jobReader.timeOut,

jobReader.title,

jobReader.description);

}

Trong phần struct mình cũng update thêm các biến liên quan tới thời gian, và để tiện xử lý mình sẽ sữ dụng Unix timestamp (Solidity không có kiểu datime nên dùng Unix time là tiện nhất):

uint256 start;

uint256 end;

uint256 timeOut;

Chúng ta có toàn bộ mã nguồn như sau:

pragma solidity ^0.4.18;





contract PartTime {



//Job structure

struct Job {

uint256 id;

address creator;

uint256 salary;

uint256 start;

uint256 end;

uint256 timeOut;

bytes title;

bytes description;

}



//New job append

event NewJob(uint256 indexed id,

address creator,

uint256 salary,

uint256 timeOut);



//An woker start working

event TakeJob(

uint256 indexed id,

address indexed labor);



//Minium accept salary

uint256 constant public MINIUM_SALARY = 0.1 ether;



//The number of jobs

uint256 public totalJob;



//Mapped data

mapping (uint256 => Job) public jobData;



//Transaction must contant Ethereum

modifier onlyHaveFund {

require(msg.value > MINIUM_SALARY);

_;

}



//Valid timeOut should be greater than 3 days

modifier onlyValidTimeOut(uint256 timeOut) {

require(timeOut > 3 days);

_;

}



//Check valid job Id

modifier onlyValidId(uint256 jobId) {

require(jobId < totalJob);

_;

}



//Mortgage should be greater than 1/10

modifier onlyValidMortgage(uint256 jobId) {

require(msg.value > jobData[jobId].salary/10);

_;

}



//Check is it a taked job

modifier onlyValidJob(uint256 jobId) {

require(jobData[jobId].end == 0);

require(jobData[jobId].start == 0);

_;

}



//Append new job to mapping

function

createJob (uint256 timeOut, bytes title, bytes description)

public onlyHaveFund onlyValidTimeOut(timeOut) payable returns(uint256 jobId)

{

// Saving a little gas by create a temporary object

Job memory newJob;



// Assign jobId

jobId = totalJob;



newJob.id = jobId;

newJob.id = timeOut;

newJob.title = title;

newJob.description = description;

newJob.salary = msg.value;

newJob.creator = msg.sender;



//Trigger event

NewJob(jobId, msg.sender, msg.value, timeOut);



// Append newJob to jobData

jobData[totalJob++] = newJob;



return jobId;

}



//Take job

function

takeJob (uint256 jobId)

public onlyValidMortgage(jobId) onlyValidId(jobId) onlyValidJob(jobId)

{

//Trigger event to log labor

TakeJob(jobId, msg.sender);



//Change working state

jobData[jobId].start = block.timestamp;

}



//Veiw job data

function

viewJob(uint256 jobId)

public onlyValidId(jobId) constant returns (

uint256 id,

address creator,

uint256 salary,

uint256 start,

uint256 end,

uint256 timeOut,

bytes title,

bytes description)

{

Job memory jobReader = jobData[jobId];

return (jobReader.id,

jobReader.creator,

jobReader.salary,

jobReader.start,

jobReader.end,

jobReader.timeOut,

jobReader.title,

jobReader.description);

}



}

Và mình viết thêm test case bằng JavaScript:

var Partime = artifacts.require("./PartTime.sol");



function createTx(from, to, value = 0, gas = 1000000, gasPrice = 20000000) {

return {

from: from,

to: to,

gas: gas,

gasPrice: gasPrice,

value: value

};

}



contract('Partime', function (accounts) {



it('should have 0 total part time job', function () {

return Partime.deployed().then(function (instance) {

return instance.totalJob.call();

}).then(function (totalJob) {

assert.equal(totalJob.valueOf(), 0, 'Total job was not equal to 0');

});

});



it('should able to add new job', function () {

return Partime.deployed().then(function (instance) {

return instance.createJob(((new Date()).getTime() / 1000 + 432000),

"This is tittle",

"This is description",

createTx(accounts[0], instance.address, web3.toWei('1', 'ether')));

}).then(function (totalJob) {

assert.equal(typeof (totalJob.valueOf()), 'object', 'Transaction was not triggered success');

});

});



it('should have total part time job geater than 0', function () {

return Partime.deployed().then(function (instance) {

return instance.totalJob.call();

}).then(function (totalJob) {

assert.equal(totalJob.valueOf() > 0, true, 'Total job was equal to 0' );

});

});



});

Bạn chú ý thấy mình đang thêm 1 job mới:

return instance.createJob(((new Date()).getTime() / 1000 + 432000),

"This is tittle",

"This is description",

createTx(accounts[0], instance.address, web3.toWei('1', 'ether')));

Đoạn code này có nghĩa là mình tạo ra 1 job có

  • Timeout: 5 ngày
  • Title: This is tittle
  • Description: This is description
  • Value: 1 Ethereum

Thực thi kiểm thử:

Smart contracts

Mình đã update source code tại https://github.com/chiro-hiro/part-time-dapp. Các bạn có thể clone về hoặc fork về viết cùng mình cho vui.

Dislaimer: Đây là thông tin cung cấp dưới dạng blog cá nhân, không phải thông tin tổng hợp hay lời khuyên đầu tư. Chúng tôi không chịu trách nhiệm về các quyết định đầu tư của bạn.

MỚI CẬP NHẬT

bitcoin

16 năm hành trình Bitcoin: Nhìn lại tweet đầu tiên khi giá bằng 0

Vào ngày 10/1/2009, lịch sử đã ghi dấu với dòng tweet đầu tiên về Bitcoin từ Hal Finney, nhà khoa học máy tính và...
bitcoin

Bitcoin cần tăng mạnh tại 88.000 đô la khi S&P 500 gợi nhớ khủng...

Bitcoin đang dao động dưới 95.000 đô la vào ngày 11/1 sau một ngày đầy biến động mang lại "phản ứng bi quan thái...
Cá voi mua dip hàng tỷ DOGE và XRP

Cá voi mua dip hàng tỷ DOGE và XRP

Sự hào hứng của cá voi tiền điện tử đang ngày càng trở nên rõ ràng hơn trong những ngày trước lễ nhậm chức...

Các nhà đầu tư chống lại đợt bán tháo, ADA có thể vượt mốc...

Cardano (ADA) đã chứng kiến biến động giá mạnh mẽ trong tháng qua, ngăn cản altcoin này giành lại mức hỗ trợ tại mốc...

Nghị sĩ Hoa Kỳ tiết lộ nắm giữ XRP, SOL và BTC

Hạ nghị sĩ Guy Reschenthaler (Đảng Cộng hòa) gần đây đã tiết lộ một loạt các giao dịch mua tiền điện tử. Nhà lập...

Tin vắn Crypto 11/01: Bitcoin vẫn có khả năng tăng trưởng theo cấp số...

Từ nhận định Bitcoin vẫn có khả năng tăng trưởng theo cấp số nhân trong thời gian tới đến Usual Protocol giới thiệu một...

World Network (WLD) vượt mốc 10 triệu lượt xác minh danh tính con người

World Network, dự án xác minh danh tính con người trên nền tảng blockchain, trước đây được biết đến với tên Worldcoin, vừa công...

Quan chức FDIC Hoa Kỳ chỉ trích các hạn chế về tiền điện tử,...

Phó chủ tịch Công ty Bảo hiểm Ký thác Liên bang (FDIC) Travis Hill đã lên tiếng chỉ trích những hành động trước đây...
Đồng sáng lập Wolf Capital nhận tội lừa đảo 9,4 triệu đô la tiền điện tử

Đồng sáng lập Wolf Capital nhận tội lừa đảo 9,4 triệu đô la tiền...

Travis Ford, đồng sáng lập và trưởng nhóm trader của công ty đầu tư tiền điện tử Wolf Capital vừa thừa nhận tội danh...

Liệu Hedera (HBAR) có thể tăng 40% lên 0,39 đô la không?

Hedera (HBAR) hiện đang gặp khó khăn trong việc đạt được đà tăng trưởng, điều này phản ánh sự thiếu định hướng trong bối...

Trader cảnh báo rủi ro Bitcoin “đang đạt đỉnh” trong chu kỳ, cẩn thận...

Một nhà phân tích Bitcoin nổi tiếng vừa cảnh báo các nhà đầu tư tiền mã hóa nên hành động thận trọng trong những tháng...

Đức khám phá việc áp dụng Bitcoin thông qua trái phiếu blockchain, dự trữ...

Các nhà hoạch định chính sách ở Đức hiện đang tích cực xem xét các chiến lược để tích hợp Bitcoin (BTC) vào hệ...

Microsoft sẽ siết chặt việc lạm dụng AI tạo sinh bởi tội phạm

Microsoft vừa đệ một đơn kiện nhằm ngăn chặn các hoạt động tội phạm mạng lợi dụng công nghệ AI tạo sinh, theo thông...

Biden nhắm vào các nhà phát triển ví crypto như MetaMask, Phantom ngày cuối...

Một động thái bất ngờ từ một quan chức được Tổng thống Joe Biden bổ nhiệm đang tìm cách yêu cầu các nhà phát...

Mùa altcoin bị kìm hãm do thiếu dòng tiền mới đổ vào lĩnh vực...

Vốn hóa thị trường altcoin hiện tại vẫn thấp hơn so với mức cao nhất mọi thời đại vào tháng 11 năm 2021, khi...
Bitcoin

“Đỉnh thị trường” Bitcoin vẫn chưa xuất hiện

Giá Bitcoin đã giảm xuống mức thấp mới là 91.055 đô la vào ngày 9/1, đánh dấu mức thấp nhất kể từ ngày 1/12....