Solidity Unit Testing plugin

The Solidity Unit Testing plugin allows you to write and run automated tests for your Solidity smart contracts to verify they work correctly before deployment.

It helps you generate test files, write test functions using a built-in assertion library (like Assert.equal, Assert.notEqual), and execute those tests in a separate environment to see pass/fail results.

Activating the Solidity unit testing plugin

To activate the plugin, go to the Plugin Manager, search « Unit Testing » and enable the « Solidity Unit Testing » plugin.

When the plugin loads, you’ll see a screen like this:

Unit testing page

Répertoire des tests

When you load the plugin, you need to specify a directory where the plugin will load and store test files. By default, it’s a tests folder at the root of your Workspace.

Note

The plugin will not automatically create directories. You must click « Create » to generate the specified folder structure.

After specifying the test folder, click the « Create » button. Alternatively, you can select an existing folder as the tests folder by typing « / » followed by the name of the folder.

Test Directory

Generating tests

The plugin can generate generic test files that contain information about developing tests for a contract. The name of the generic test file is determined by the currently active .sol file on the Main Panel. If there is no active file, a generic test file named, newFile_test.sol will be created.

Below is an example of a generic test file:

pragma solidity >=0.4.22 <0.8.0;
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "remix_accounts.sol";
// Import here the file to test.

// File name has to end with '_test.sol', this file can contain more than one testSuite contracts
contract testSuite {

    /// 'beforeAll' runs before all other tests
    /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll'
    function beforeAll() public {
        // Here should instantiate tested contract
        Assert.equal(uint(1), uint(1), "1 should be equal to 1");
    }

    function checkSuccess() public {
        // Use 'Assert' to test the contract,
        // See documentation: https://remix-ide.readthedocs.io/en/latest/assert_library.html
        Assert.equal(uint(2), uint(2), "2 should be equal to 2");
        Assert.notEqual(uint(2), uint(3), "2 should not be equal to 3");
    }

    function checkSuccess2() public pure returns (bool) {
        // Use the return value (true or false) to test the contract
        return true;
    }

    function checkFailure() public {
        Assert.equal(uint(1), uint(2), "1 is not equal to 2");
    }

    /// Custom Transaction Context
    /// See more: https://remix-ide.readthedocs.io/en/latest/unittesting.html#customization
    /// #sender: account-1
    /// #value: 100
    function checkSenderAndValue() public payable {
        // account index varies 0-9, value is in wei
        Assert.equal(msg.sender, TestsAccounts.getAccount(1), "Invalid sender");
        Assert.equal(msg.value, 100, "Invalid value");
    }
}

Writing tests

Rédigez suffisamment de tests unitaires pour vous assurer que votre contrat fonctionne comme prévu dans différents scénarios.

Remix injects a built-in assert library for testing. You can visit the library documentation here.

Additionally, Remix allows the usage of special functions in the test file to make testing more structural. They are:

  • beforeEach() - S’exécute avant chaque test

  • beforeAll() - S’exécute avant tous les tests

  • afterEach() - S’exécute après chaque test

  • afterAll() - S’exécute après tous les tests

To get started, see this simple example.

Astuce

You can use RemixAI to generate tests for your files.

Running tests

Once you are done with writing tests, select the file(s) and click on Run to execute the tests. The execution will run in a separate environment. After completing the execution of one file, a test summary will be shown:

Pour les tests qui ont échoué, il y aura plus de détails d’assertion pour analyser le problème. Si vous cliquez sur un test qui a échoué, la ligne de code correspondante sera mise en évidence dans l’éditeur.

Stopping tests

Si vous avez sélectionné plusieurs fichiers pour exécuter les tests et que vous souhaitez arrêter l’exécution, cliquez sur le bouton « Stop ». L’exécution s’arrêtera après avoir exécuté les tests pour le fichier en cours.

Customizing tests

Remix offre aux utilisateurs différents types de personnalisation pour tester correctement un contrat.

1. Custom Compiler Context

Solidity Unit Testing refers to the Solidity Compiler plugin for compiler configurations. Configure Compiler, EVM Version, Enable Optimization & runs in the Solidity Compiler plugin and this will be used in the Solidity Unit Testing plugin for contract compilation before running unit tests.

2. Custom Transaction Context

For interacting with a contract’s method, the main parameters of a transaction are from address, value & gas. Typically, a method’s behaviour is tested with different values of these parameters.

On peut saisir des valeurs personnalisées pour msg.sender et msg.value de la transaction en utilisant les commentaires NatSpec, comme par exemple :

/// #sender: account-0
/// #value: 10
function checkSenderIs0AndValueis10 () public payable {
    Assert.equal(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIs0AndValueis10");
    Assert.equal(msg.value, 10, "wrong value in checkSenderIs0AndValueis10");
}

Instructions to use:

  1. Les paramètres doivent être définis dans la NatSpec de la méthode

  2. Chaque clé de paramètre doit être préfixée par un hash (#) et se terminer par deux points après un espace (** : **) comme #sender : & #value :

  3. Pour l’instant, la personnalisation n’est disponible que pour les paramètres sender et value

  4. L’expéditeur est l’adresse from d’une transaction à laquelle on accède en utilisant msg.sender à l’intérieur d’une méthode de contrat. Il doit être défini dans un format fixe comme « account-<account_index> ».

  5. <account_index> varie de 0-2 avant la sortie de la version 0.10.0 de remix-ide et de 0-9 après.

  6. remix_accounts.sol must be imported in your test file to use custom sender

  7. La valeur est la valeur envoyée avec une transaction dans wei et à laquelle on accède en utilisant msg.value à l’intérieur d’une méthode de contrat. Il doit s’agir d’un nombre.

Regarding gas, Remix estimates the required gas for each transaction internally. Still if a contract deployment fails with Out-of-Gas error, it tries to redeploy it by doubling the gas. Deployment failing with double gas will show error: contract deployment failed after trying twice: The contract code couldn't be stored, please check your gas limit

Various test examples can be seen in examples section.

Points à retenir

  • Un contrat de test ne peut pas avoir de méthode avec des paramètres. Si vous avez une telle méthode, vous obtiendrez l’erreur suivante : La méthode 'nom de la méthode' ne peut pas avoir de paramètres à l'intérieur d'un contrat de test

  • Le nombre de comptes de test est de 3 avant la sortie de la version 0.10.0 de remix-ide et de 10 après.

  • While a test file which imports remix_accounts.sol might not compile successfully with Solidity Compiler plugin, do not worry, this will have no bearing on its success with Solidity Unit Testing plugin.