Brownie relay on Pytest for smart contracts testing. For testing purpose we will need only two new files inside: ./tests
folder: conftest.py
and test_contracts.py
helpers.py
file have (we already create for deployment purpose) one function which returns eth acocunts from which we will deploy our contracts inisde our test.
conftest.py
is used to set-up initial conditions in which we can test some smart-contract functionality. For this purpose we will use @pytest.fixtures
decorators. This will allow us to pass them as argument to our test and on this way to set-up intial conditions in which we can test our smart contract functionality. Here is code for conftest.py
(more explanation in comments):
#!/usr/bin/python3
import pytest
#function for loading account
from scripts.helpers import get_account
initial_supply = 1000
max_nft = 100
"""
Defining a Shared Initial State for this test. A common pattern in testing is to include one or more module-scoped setup fixtures that define the
initial test conditions, and then use fn_isolation (next step) to revert to this base state at the start of each test.
"""
@pytest.fixture(scope="module", autouse=True)
def initial_supply_of_mock_tokens():
# return intial_supplay of MockUSDC tokens
return initial_supply
@pytest.fixture(scope="module", autouse=True)
def smartContract_deploy(MusicNFT, MockUSDC):
account = get_account()
# deploy MockUSDC contract
mock_token = MockUSDC.deploy(initial_supply, {"from": account[0]})
# deploy MusciNFT contract
musicNFTtoken = MusicNFT.deploy(mock_token, 10, {"from": account[0]})
# return depoyment addresses of both contract. What deploy method return is much more richer, but in this moment we use just address
return mock_token, musicNFTtoken
"""
In many cases we want to isolate our tests from one another by resetting the local environment. Without isolation, it is possible that the outcome of
a test will be dependent on actions performed in a previous test. This is done by following function.
"""
@pytest.fixture(scope="function", autouse=True)
def isolate(fn_isolation):
# perform a chain rewind after completing each test, to ensure proper isolation
# https://eth-brownie.readthedocs.io/en/v1.10.3/tests-pytest-intro.html #isolation-fixtures
pass
@pytest.fixture(scope="module")
def test_accounts():
account_1, account_2 = get_account()
return account_1, account_2
What we miss now is just test_contract.py
file. Here si more details
#!/usr/bin/python3
# Test if deployment whent well and if address pf deployed contracts starts with 0x
def test_initial_supplay_account_alice(smartContract_deploy):
mock_token, musicNFTtoken = smartContract_deploy
assert mock_token.address.startswith("0x")
assert musicNFTtoken.address.startswith("0x")
# Test if right ammount of MockTokens are minted to deployer/owner address
def test_mock_token(initial_supply_of_mock_tokens, smartContract_deploy, test_accounts):
mock_token, musicNFTtoken = smartContract_deploy
deployer_account, user_account = test_accounts
initial_supply = initial_supply_of_mock_tokens
mock_token_balance = mock_token.balanceOf(deployer_account)
assert mock_token_balance == 1000_000_000_000_000_000_000
# Test approve & allowance functionality. Reason for this is fact that when we have crypto
# buyers for NFTs we will need to transfer from our user to our smart contract certain
# amount of USDC tokens. And because we will call USDC contract from our MusicNFT contract
# we will need to have rights to spend user USDC by transfering from his account to
# our account.
def test_mock_token_approve_allow(smartContract_deploy, test_accounts):
accountOne, accountTwo = test_accounts
mock_token, musicNFTtoken = smartContract_deploy
mock_token.approve(musicNFTtoken.address, 1000)
result = mock_token.allowance(accountOne, musicNFTtoken.address)
assert result == 1000
# And now finally let's test our NFT contract. And here in this test we will check whole buy with crypto flow.
# And this includes: buyer approve our NFT contract to spend USDC
# for NFT in this name.
def test_NFT_buy_with_crypto(smartContract_deploy, test_accounts):
mock_token, musicNFTtoken = smartContract_deploy
deployer_account, user_account = test_accounts
mock_token.approve(musicNFTtoken.address, 1000)
result = mock_token.allowance(deployer_account, musicNFTtoken.address)
assert result == 1000
mock_token.transfer(musicNFTtoken.address, 1000)
mock_token_balance = mock_token.balanceOf(musicNFTtoken.address)
assert mock_token_balance == 1000
Let's run test
$brownie test -v
=============================================================================== 4 passed in 2.54s ================================================================================
Terminating local RPC client...
(env) brownie_musical_nfts/tests git:(main) ✗ ➜ brownie test -v
Brownie v1.19.3 - Python development framework for Ethereum
============================================================================== test session starts ===============================================================================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /home/ilija/code/my_tutorials/musical_nft_thumbnails/smart-contracts/env/bin/python3
cachedir: tests/.pytest_cache
hypothesis profile 'brownie-verbose' -> verbosity=2, deadline=None, max_examples=50, stateful_step_count=10, report_multiple_bugs=False, database=DirectoryBasedExampleDatabase(PosixPath('/home/ilija/.brownie/hypothesis'))
rootdir: /home/ilija/code/my_tutorials/musical_nft_thumbnails/smart-contracts/brownie_musical_nfts
plugins: eth-brownie-1.19.3, forked-1.4.0, hypothesis-6.27.3, web3-5.31.3, xdist-1.34.0
collected 4 items
This version of µWS is not compatible with your Node.js build:
Error: Cannot find module './uws_linux_x64_111.node'
Falling back to a NodeJS implementation; performance may be degraded.
Launching 'ganache-cli --chain.vmErrorsOnRPCResponse true --server.port 8545 --miner.blockGasLimit 12000000 --wallet.totalAccounts 20 --hardfork istanbul --wallet.mnemonic attitude grant adjust accuse mail visual hammer potato nest interest breeze crime --wallet.defaultBalance 200'...
test_contracts.py::test_initial_supplay_account_alice PASSED [ 25%]
test_contracts.py::test_mock_token PASSED [ 50%]
test_contracts.py::test_mock_token_approve_allow PASSED [ 75%]
test_contracts.py::test_NFT_buy_with_crypto PASSED [100%]
=============================================================================== 4 passed in 2.41s ================================================================================
In this moment we should have our smart-ontract written, tested and deployed. Next step is integration with Django backend.
Code can be found in github repo
Top comments (1)
message me now on fiverr.com/rasbak_stars