Lição 4

Testing the Contract

Welcome to Lesson 4 of our deep dive into tokenization on Tezos! In this section, we will explore the importance of thorough testing in the development process and how to carry out these tests using the testing suite provided within the smart contract. We're still working with the SmartPy online IDE as our development environment and we have our interface opened after running the contract.

Introduction

Smart contracts are immutable once deployed on the blockchain, which means they can’t be modified. Therefore, any bugs or security vulnerabilities can have serious consequences, making testing an indispensable step in the development process.

In this lesson, we will discuss the Fa1_2TestFull contract, which includes a series of tests designed to verify the functionality of our token contract.

The Fa1_2TestFull Contract

The Fa1_2TestFull contract is a class that inherits all the functionalities from the different contracts like Admin, Pause, Fa1_2, Mint, Burn, and ChangeMetadata. It’s used to aggregate all these functionalities and perform a thorough test to ensure the contract is working as expected.

Python
class Fa1_2TestFull(Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
        def __init__(self, administrator, metadata, ledger, token_metadata):
            ChangeMetadata.__init__(self)
            Burn.__init__(self)
            Mint.__init__(self)
            Fa1_2.__init__(self, metadata, ledger, token_metadata)
            Pause.__init__(self)
            Admin.__init__(self, administrator)

The Fa1_2TestFull class constructor initializes all of the functionalities.

Setting Up a Test

For our contract, we start by setting up the testing scenario with test accounts and the contract initialization. This is done within a test function decorated with @sp.add_test.

Python
@sp.add_test(name="FA12")def test():
    # Initialize test scenario and accounts
    sc = sp.test_scenario(m)
    admin = sp.test_account("Administrator")
    alice = sp.test_account("Alice")
    bob = sp.test_account("Robert")

    # Initialize contract with some initial values
    token_metadata = {
        "decimals": sp.utils.bytes_of_string("18"),  # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"),  # Recommended"symbol": sp.utils.bytes_of_string("MGT"),  # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
    }
    contract_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
    c1 = m.Fa1_2TestFull(administrator=admin.address,metadata=contract_metadata,token_metadata=token_metadata,ledger={},)
    sc += c1

We define the test accounts: Admin, Alice, and Bob. Then we initialize our contract, Fa1_2TestFull, with some initial values. The += operator adds the contract to the scenario.

From now on, to help you better understand the code, the code will be on the left and a visualisation of the code line highlighted will be on the right. Example here:

Running Tests

The next step is to run tests, and this involves triggering different contract functions and verifying the results.

For example, to test the minting functionality, we run:

Python
sc.h2("Admin mints a few coins")
c1.mint(address=alice.address, value=12).run(sender=admin)

This line runs a test where the admin mints 12 tokens for Alice. If the function successfully mints the tokens and correctly updates Alice’s balance, then this test passes.

Verifying Results

SmartPy provides the verify method to ensure that a condition holds true. If the condition is not met, the test will fail. For example:

Python
 c1.update_metadata(key="", value=sp.bytes("0x00")).run(sender=admin)
        sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))

Those lines verify that the contract’s metadata was correctly updated to "0x00". If it was not updated correctly, the test fails.

Advanced Testing

Your smart contract tests should cover all possible use cases, including edge cases and potential failures. These can include transfers exceeding a user’s balance, burning tokens when the contract is paused, etc.

For example, a failed transfer test could look like this:

Python
sc.h2("Bob tries to transfer from Alice but he doesn't have her approval")
c1.transfer(from_=alice.address, to_=bob.address, value=4).run(sender=bob, valid=False)

Here, Bob tries to transfer 4 tokens from Alice’s account without having approval. Since this operation should fail, we set valid=False in the run function. If the contract correctly prevents the transfer, the test passes.

Recap

Testing is crucial in smart contract development. Given the immutable nature of blockchain, any error in a contract can have permanent and potentially costly consequences. Writing comprehensive tests ensures that all functions behave as expected, leading to robust and secure contracts.

Remember to write tests for both positive and negative cases. Positive cases validate that a function works correctly when used as intended. Negative cases ensure the contract behaves correctly in handling incorrect or unexpected inputs.

Exclusão de responsabilidade
* O investimento em criptomoedas envolve riscos significativos. Prossiga com cuidado. O curso não pretende ser um conselho de investimento.
* O curso é criado pelo autor que se juntou ao Gate Learn. Qualquer opinião partilhada pelo autor não representa o Gate Learn.
Catálogo
Lição 4

Testing the Contract

Welcome to Lesson 4 of our deep dive into tokenization on Tezos! In this section, we will explore the importance of thorough testing in the development process and how to carry out these tests using the testing suite provided within the smart contract. We're still working with the SmartPy online IDE as our development environment and we have our interface opened after running the contract.

Introduction

Smart contracts are immutable once deployed on the blockchain, which means they can’t be modified. Therefore, any bugs or security vulnerabilities can have serious consequences, making testing an indispensable step in the development process.

In this lesson, we will discuss the Fa1_2TestFull contract, which includes a series of tests designed to verify the functionality of our token contract.

The Fa1_2TestFull Contract

The Fa1_2TestFull contract is a class that inherits all the functionalities from the different contracts like Admin, Pause, Fa1_2, Mint, Burn, and ChangeMetadata. It’s used to aggregate all these functionalities and perform a thorough test to ensure the contract is working as expected.

Python
class Fa1_2TestFull(Admin, Pause, Fa1_2, Mint, Burn, ChangeMetadata):
        def __init__(self, administrator, metadata, ledger, token_metadata):
            ChangeMetadata.__init__(self)
            Burn.__init__(self)
            Mint.__init__(self)
            Fa1_2.__init__(self, metadata, ledger, token_metadata)
            Pause.__init__(self)
            Admin.__init__(self, administrator)

The Fa1_2TestFull class constructor initializes all of the functionalities.

Setting Up a Test

For our contract, we start by setting up the testing scenario with test accounts and the contract initialization. This is done within a test function decorated with @sp.add_test.

Python
@sp.add_test(name="FA12")def test():
    # Initialize test scenario and accounts
    sc = sp.test_scenario(m)
    admin = sp.test_account("Administrator")
    alice = sp.test_account("Alice")
    bob = sp.test_account("Robert")

    # Initialize contract with some initial values
    token_metadata = {
        "decimals": sp.utils.bytes_of_string("18"),  # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"),  # Recommended"symbol": sp.utils.bytes_of_string("MGT"),  # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
    }
    contract_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
    c1 = m.Fa1_2TestFull(administrator=admin.address,metadata=contract_metadata,token_metadata=token_metadata,ledger={},)
    sc += c1

We define the test accounts: Admin, Alice, and Bob. Then we initialize our contract, Fa1_2TestFull, with some initial values. The += operator adds the contract to the scenario.

From now on, to help you better understand the code, the code will be on the left and a visualisation of the code line highlighted will be on the right. Example here:

Running Tests

The next step is to run tests, and this involves triggering different contract functions and verifying the results.

For example, to test the minting functionality, we run:

Python
sc.h2("Admin mints a few coins")
c1.mint(address=alice.address, value=12).run(sender=admin)

This line runs a test where the admin mints 12 tokens for Alice. If the function successfully mints the tokens and correctly updates Alice’s balance, then this test passes.

Verifying Results

SmartPy provides the verify method to ensure that a condition holds true. If the condition is not met, the test will fail. For example:

Python
 c1.update_metadata(key="", value=sp.bytes("0x00")).run(sender=admin)
        sc.verify(c1.data.metadata[""] == sp.bytes("0x00"))

Those lines verify that the contract’s metadata was correctly updated to "0x00". If it was not updated correctly, the test fails.

Advanced Testing

Your smart contract tests should cover all possible use cases, including edge cases and potential failures. These can include transfers exceeding a user’s balance, burning tokens when the contract is paused, etc.

For example, a failed transfer test could look like this:

Python
sc.h2("Bob tries to transfer from Alice but he doesn't have her approval")
c1.transfer(from_=alice.address, to_=bob.address, value=4).run(sender=bob, valid=False)

Here, Bob tries to transfer 4 tokens from Alice’s account without having approval. Since this operation should fail, we set valid=False in the run function. If the contract correctly prevents the transfer, the test passes.

Recap

Testing is crucial in smart contract development. Given the immutable nature of blockchain, any error in a contract can have permanent and potentially costly consequences. Writing comprehensive tests ensures that all functions behave as expected, leading to robust and secure contracts.

Remember to write tests for both positive and negative cases. Positive cases validate that a function works correctly when used as intended. Negative cases ensure the contract behaves correctly in handling incorrect or unexpected inputs.

Exclusão de responsabilidade
* O investimento em criptomoedas envolve riscos significativos. Prossiga com cuidado. O curso não pretende ser um conselho de investimento.
* O curso é criado pelo autor que se juntou ao Gate Learn. Qualquer opinião partilhada pelo autor não representa o Gate Learn.