Cara menguji kontrak yang cerdas

gambar

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:

  1. Cara menyiapkan lingkungan pengujian.
  2. 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 :

gambar

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:

gambar

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:

  1. Penerimaan dan jumlah donasi.
  2. Apakah sejumlah donasi telah tercapai.
  3. Apa yang terjadi jika Anda menyumbang lebih dari yang perlu Anda kumpulkan.
  4. Jumlah total donasi.
  5. 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:

  1. Untuk mencari peristiwa (events) dan memeriksa argumennya, fungsi findEvent kecil ditulis.
  2. 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:

gambar

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.

Source: https://habr.com/ru/post/id432012/


All Articles