
Ketentuan kontrak pintar tidak dapat diubah. Karena itu, setiap kali Anda membuat kontrak pintar, Anda perlu memastikan bahwa itu bekerja dengan benar. Pengujian adalah cara yang aman untuk menguji kontrak dalam situasi yang berbeda. Dalam tutorial ini, Anda akan mempelajari langkah-langkah apa yang harus diambil.
Saya akan memberi tahu:
- Cara menyiapkan lingkungan pengujian.
- Cara menulis tes JavaScript dan menjalankannya dalam Truffle .
Tutorial ini ditujukan untuk pemula yang baru saja mulai mempelajari pengembangan dan pengujian kontrak pintar di Ethereum. Untuk memahami tutorial ini, Anda harus memiliki setidaknya pengetahuan dasar tentang
JavaScript dan
Soliditas .
1. Cara menyiapkan lingkungan pengujian
Ada banyak cara untuk menguji kontrak yang cerdas, tetapi
Truffle adalah alat penulisan tes yang paling populer menggunakan
JavaScript . Pada
Truffle, Anda dapat menulis pengujian unit atau melakukan pengujian integrasi penuh dengan parameter nyata dari lingkungan produksi.
Pertama, Anda perlu menginstal Node.js versi terbaru dari
situs resmi .
Kemudian buka terminal dan instal
Truffle menggunakan perintah berikut:
npm install -g truffle
Setelah menginstal
Truffle , tanpa menutup terminal, buat direktori
Pendanaan :
mkdir Funding
Selanjutnya, buka direktori dengan perintah:
cd Funding
Untuk menginisialisasi direktori, jalankan perintah:
truffle init
Setelah menjalankan perintah, folder dan file berikut ini akan dibuat di direktori
Pendanaan :

Selanjutnya kami akan bekerja dengan setiap direktori. Sementara itu, kami terus mempersiapkan lingkungan pengujian.
Untuk menjalankan tes, Anda perlu perpustakaan Javascript.
Mocha adalah perpustakaan yang berisi fungsi umum untuk pengujian, termasuk
menjelaskan dan
itu .
Chai adalah perpustakaan yang mendukung berbagai fungsi untuk pemeriksaan. Ada "gaya" yang berbeda untuk memeriksa hasil, dan Chai memberi kita kesempatan ini. Dalam tutorial kita akan menggunakan
Harus .
Secara default, Mocha adalah bagian dari Truffle, kita dapat dengan mudah menggunakan fungsi perpustakaan. Chai harus diinstal secara manual. Untuk melakukan ini, gunakan terminal dan di direktori root proyek, jalankan perintah:
npm install chai
Saya juga menginstal
perpustakaan chai-bignumber untuk membandingkan angka dengan presisi sewenang-wenang:
npm install --save-dev chai-bignumber
Lingkungan pengujian siap untuk ini. Sekarang Anda dapat mulai mengembangkan kontrak yang cerdas dan mengujinya.
2. Cara menulis tes JavaScript dan menjalankannya dalam Truffle
Untuk mengembangkan tes, Anda memerlukan kontrak yang cerdas. Kami akan mengembangkan kontrak yang memungkinkan Anda untuk mengumpulkan sumbangan, menetapkan jumlah tertentu untuk mencapai pengumpulan dan menarik dana. Jika seseorang menyumbang lebih banyak, perbedaan antara jumlah yang telah diakumulasikan dan jumlah yang perlu dikumpulkan akan dikembalikan kepadanya.
Pergi ke direktori
Pendanaan -> kontrak . Dalam
Pendanaan / kontrak, buat file
Funding.sol dengan ekstensi
.sol - ini akan menjadi kontrak cerdas untuk pengujian.
Di
Funding.sol, tambahkan kode berikut:
pragma solidity 0.4.24; contract Funding { uint public raised; uint public goal; address public owner; event Donated(uint donation); event Withdrew(uint amount); modifier onlyOwner() { require(owner == msg.sender); _; } modifier isFinished() { require(isFunded()); _; } modifier notFinished() { require(!isFunded()); _; } constructor (uint _goal) public { owner = msg.sender; goal = _goal; } function isFunded() public view returns (bool) { return raised >= goal; } function donate() public payable notFinished { uint refund; raised += msg.value; if (raised > goal) { refund = raised - goal; raised -= refund; msg.sender.transfer(refund); } emit Donated(msg.value); } function withdraw() public onlyOwner isFinished { uint amount = address(this).balance; owner.transfer(amount); emit Withdrew(amount); } }
Kontrak sudah siap. Kami akan menggunakan kontrak pintar melalui migrasi.
Migrasi adalah file
JavaScript yang membantu Anda menggunakan kontrak di jaringan Ethereum. Ini adalah cara utama untuk menyebarkan kontrak.
Buka direktori
Pendanaan -> migrasi dan buat file
2_funding.js , tambahkan kode berikut ke dalamnya:
const Funding = artifacts.require("./Funding.sol"); const ETHERS = 10**18; const GOAL = 20 * ETHERS; module.exports = function(deployer) { deployer.deploy(Funding, GOAL); };
Untuk menjalankan tes, Anda harus menggunakan perintah
tes truffle . Di terminal, buka akar direktori
Pendanaan , yang dibuat selama persiapan lingkungan pengujian dan masukkan:
truffle test
Jika output berikut muncul di terminal, maka semuanya dilakukan dengan benar:

Sekarang mari kita mulai menulis tes.
Verifikasi Pemilik
Pergi ke direktori
tes Pendanaan -> dan buat file
test_funding.js dengan ekstensi
.js . Ini adalah file di mana tes akan ditulis.
Tambahkan kode berikut ke file
test_funding.js :
const Funding = artifacts.require("Funding"); require("chai").use(require("chai-bignumber")(web3.BigNumber)).should(); contract("Funding", function([account, firstDonator, secondDonator]) { const ETHERS = 10**18; const GAS_PRICE = 10**6; let fundingContract = null; it("should check the owner is valid", async () => { fundingContract = await Funding.deployed(); const owner = await fundingContract.owner.call() owner.should.be.bignumber.equal(account); });
Dalam pengujian, kami memverifikasi bahwa kontrak
Pendanaan menyimpan alamat pemilik yang menyebarkan kontrak. Dalam kasus kami,
akun adalah elemen pertama dari array.
Truffle memungkinkan Anda untuk menggunakan hingga sepuluh alamat, dalam pengujian kami hanya membutuhkan tiga alamat.
Penerimaan sumbangan dan verifikasi akhir penggalangan dana
Di bagian ini kami akan memeriksa:
- Penerimaan dan jumlah donasi.
- Apakah sejumlah donasi telah tercapai.
- Apa yang terjadi jika Anda menyumbang lebih dari yang perlu Anda kumpulkan.
- Jumlah total donasi.
- Dapatkah saya terus mengumpulkan dana jika jumlah yang diminta telah dikumpulkan.
Kami akan menulis dan menganalisis tes:
. . . . . . . . . . . . . . . . . . . . . . const ETHERS = 10**18; const GAS_PRICE = 10**6; let fundingContract = null; let txEvent; function findEvent(logs, eventName) { let result = null; for (let log of logs) { if (log.event === eventName) { result = log; break; } } return result; }; it("should accept donations from the donator #1", async () => { const bFirstDonator= web3.eth.getBalance(firstDonator); const donate = await fundingContract.donate({ from: firstDonator, value: 5 * ETHERS, gasPrice: GAS_PRICE }); txEvent = findEvent(donate.logs, "Donated"); txEvent.args.donation.should.be.bignumber.equal(5 * ETHERS); const difference = bFirstDonator.sub(web3.eth.getBalance(firstDonator)).sub(new web3.BigNumber(donate.receipt.gasUsed * GAS_PRICE)); difference.should.be.bignumber.equal(5 * ETHERS); });
Sebelum menguraikan tes, saya ingin mencatat 2 poin:
- Untuk mencari peristiwa (events) dan memeriksa argumennya, fungsi findEvent kecil ditulis.
- Untuk kenyamanan pengujian dan perhitungan, nilai intrinsik untuk gas ditetapkan (GAS_PRICE konstan).
Sekarang mari kita menganalisis tesnya. Dalam tes, kami memeriksa:
- bahwa kami dapat menerima donasi dengan memanggil metode donate () ;
- bahwa jumlah yang disumbangkan kepada kami ditunjukkan dengan benar;
- bahwa orang yang menyumbangkan dana, saldo menurun dengan jumlah yang disumbangkan.
it("should check if donation is not completed", async () => { const isFunded = await fundingContract.isFunded(); isFunded.should.be.equal(false); });
Dalam tes ini, kami memeriksa bahwa penggalangan dana belum selesai.
it("should not allow to withdraw the fund until the required amount has been collected", async () => { let isCaught = false; try { await fundingContract.withdraw({ gasPrice: GAS_PRICE }); } catch (err) { isCaught = true; } isCaught.should.be.equal(true); });
Dalam tes kami memeriksa bahwa kami tidak dapat menarik dana sampai jumlah yang kami butuhkan dikumpulkan.
it("should accept donations from the donator #2", async () => { const bSecondDonator= web3.eth.getBalance(secondDonator); const donate = await fundingContract.donate({ from: secondDonator, value: 20 * ETHERS, gasPrice: GAS_PRICE }); txEvent = findEvent(donate.logs, "Donated"); txEvent.args.donation.should.be.bignumber.equal(20 * ETHERS); const difference = bSecondDonator.sub(web3.eth.getBalance(secondDonator)).sub(new web3.BigNumber(donate.receipt.gasUsed * GAS_PRICE)); difference.should.be.bignumber.equal(15 * ETHERS); });
Dalam tes kami memeriksa bahwa jika Anda menyumbangkan jumlah besar, metode
donate () menghitung dan mengembalikan dana kepada orang yang menyumbang lebih dari yang diperlukan. Jumlah ini adalah perbedaan antara jumlah yang diakumulasikan dan jumlah yang ingin Anda kumpulkan.
it("should check if the donation is completed", async () => { const notFunded = await fundingContract.isFunded(); notFunded.should.be.equal(true); }); it("should check if donated amount of money is correct", async () => { const raised = await fundingContract.raised.call(); raised.should.be.bignumber.equal(20 * ETHERS); }); it("should not accept donations if the fundraising is completed", async () => { let isCaught = false; try { await fundingContract.donate({ from: firstDonator, value: 10 * ETHERS }); } catch (err) { isCaught = true; } isCaught.should.be.equal(true); });
Dalam tiga tes ini, kami memeriksa:
- bahwa penggalangan dana selesai;
- bahwa jumlah donasi sudah benar;
- bahwa tidak ada orang lain yang dapat menyumbang, karena penggalangan dana telah selesai.
Tarik dana
Di bagian tutorial sebelumnya, kami mengumpulkan jumlah yang kami butuhkan, sekarang dapat ditampilkan:
. . . . . . . . . . . . . . . . . . . . . . it("should allow the owner to withdraw the fund", async () => { const bAccount = web3.eth.getBalance(account); const withdraw = await fundingContract.withdraw({ gasPrice: GAS_PRICE }); txEvent = findEvent(withdraw.logs, "Withdrew"); txEvent.args.amount.should.be.bignumber.equal(20 * ETHERS); const difference = web3.eth.getBalance(account).sub(bAccount); difference.should.be.bignumber.equal(await fundingContract.raised.call() - withdraw.receipt.gasUsed * GAS_PRICE); });
Dengan memanggil fungsi
withdraw () , kami menarik dana pemilik kontrak pintar, dalam
akun kasing kami. Kemudian kami memeriksa bahwa kami benar-benar menarik jumlah yang kami butuhkan. Untuk melakukan ini,
tulis perbedaan dalam saldo sebelum dan sesudah penarikan dana ke dalam
perbedaan konstan. Hasilnya dibandingkan dengan jumlah donasi dikurangi biaya transaksi. Seperti disebutkan di atas, untuk kenyamanan pengujian dan perhitungan, saya menetapkan harga
gas saya sendiri.
Jalankan tes tertulis dengan perintah
tes truffle . Jika semuanya dilakukan dengan benar, hasilnya harus sebagai berikut:

Hasil
Saya mencoba menggambarkan langkah-langkah pengujian kontrak cerdas dalam bahasa yang sederhana dan mudah dipahami: mulai dari mempersiapkan lingkungan pengujian hingga menulis tes itu sendiri.
Sekarang Anda dapat menguji kontrak pintar apa pun dan memastikannya berfungsi dengan benar.