Testy i ulepszanie kontraktu – part 1

Testy i ulepszanie kontraktu – part 1

Nasz pierwszy kontrakt działa tylko dla jednego dokumentu. Warto zwiększyć jego funkcjonalność a przy okazji zautomatyzować testy. Dzisiaj testy i ulepszanie kontraktu.

Zmiana wirtualnego środowiska Ethereum

Z uwagi na to, że testrpc weszło w skład narzędzi dostarczanych od Truffle postanowiłem przerzucić się na Ganache (prywatny blockchain z graficznym interfejsem – testrpc pod spodem).

Ściągamy i instalujemy Ganache. Po uruchomieniu aplikacji powinniśmy ujrzeć interfejs graficzny z naszym blockchainem:

Zwróćcie uwagę, na jakim porcie nasłuchuje Wasze nowe środowisko, u mnie jest to 7545. Musimy dokonać zmiany w pliku konfiguracyjnym truffle.js:

 
module.exports = {
 networks: {
 development: {
 host: "localhost",
 port: 7545, //tutaj zmieniamy port
 network_id: "*"
 }
}
};

Automatyzacja testów

Testowanie kontraktu przez konsolę na dłuższą metę może stać się męczące. Truffle daje nam możliwość zautomatyzowania testów (możemy je pisać w języku Solidity lub w Javascript). Jeżeli jesteście na początkowym stadium programowania, to nie bagatelizujcie testów. Gdy projekt ciągle się rozwija i dodatkowo pracuje przy nim kilku programistów, to bez testów można wpędzić się w niezłe tarapaty. Wyróbcie sobie nawyk pisania zautomatyzowanych testów, będzie mniej niespodzianek.

Testy w Solidity

Tworzymy nowy plik w katalogu test o nazwie TestProofOfExistence1.sol, a w nim:

 
pragma solidity ^0.4.4;

import "truffle/Assert.sol"; //biblioteka do testowania
import "truffle/DeployedAddresses.sol"; // addresy do wykorzystania 
import "../contracts/ProofOfExistence1.sol"; // kontrakt do testowania

contract TestProofOfExistence1 {
	// pobranie adresu
	ProofOfExistence1 poe = 
ProofOfExistence1(DeployedAddresses.ProofOfExistence1());	
	
	function testNotarize() public {
	
	// wywołujemy funkcję, która hashuje i zapisuje nasz dokument w state
	poe.notarize('Kopalnia Programisty');
	
	// pobieramy state, który siedzi w zmiennej proof i zapisujemy go
	bytes32 returned = poe.proof();

	// wykonujemy tylko hashowanie z zapisaniem hasha do zmiennej expected
	bytes32 expected = poe.proofFor('Kopalnia Programisty');
	
	// porównujemy dwa obiekty i zwracamy wynik testu
	Assert.equal(returned, expected, 
"Proof of Existence smart contract seems to be working!");
	}

}

Powyższy kod wykonuje dokładnie taki sam scenariusz testów jak w poprzednim wpisie, gdy robiliśmy pierwsze interakcje z kontraktem przez console od truffle.

Jeżeli macie uruchomione środowisko Ganache to sprawdźmy, czy nasze testy zakończą się powodzeniem:

 
truffle.cmd compile 
truffle.cmd migrate
truffle.cmd test

Test zakończony sukcesem, ale kompilator zwrócił nam jedno ostrzeżenie. Do wersji 0.4.17 mogliśmy używać constant dla oznaczenia funkcji, które nie zmieniają stanu, ale wprowadzono dwa nowe oznaczenia:

  • view – wskazujemy, że funkcja nie zmienia stanu w żaden sposób
  • pure – bardziej restrykcyjna funkcja, nie zmienia stanu w żaden sposób i nawet nie odczytuje stanu obiektu

Nasze funkcja proofFor tylko korzysta z funkcji wbudowanej, nie odwołujemy się tam w żaden sposób do stanu obiektu, więc musimy zamienić constant na pure.

Po zmianie:

Wszystko zakończone sukcesem, zwróć też uwagę co się dzieje w Ganache. Możemy sprawdzić ile bloków jest w naszej sieci, jakie pojawiły się transakcję lub zweryfikować wszystko za pomocą logów znanych nam z testrpc.

Testy w Javascript

Tworzymy nowy plik w katalogu test o nazwie TestProofOfExistence2.js, a w nim:

 
const ProofOfExistence1 = artifacts.require('ProofOfExistence1');

contract('TestProofOfExistence2', async function() {
	let poe = await ProofOfExistence1.deployed();
	
	it('Proof of Existence notarize seems to be working!', async () => {
		await poe.notarize('Kopalnia Programisty');
		
		let returned = await poe.proof();
		let expected = await poe.proofFor('Kopalnia Programisty');
		
		assert.equal(returned, expected,'Proof of Existence notarize error');
	})
})

Truffle używa frameworka Mocha do testowania w Javascript. Mamy dwie opcje do wyboru: zagnieżdżamy i używamy .THEN lub robimy to zgrabniej z ASYNC/AWAIT. Ja wybrałem opcję drugą, kod jest zdecydowanie czytelniejszy.

Wykonajmy nasze testy:

 
truffle.cmd test

Na tym zakończmy część pierwszą, w drugiej podrasujemy nasz kontrakt i oczywiście napiszemy do niego porcję testów.

Przydatne materiały