Plugin de test unitaire

Cliquez sur l’icône (double vérification) de la barre d’icônes pour accéder au plugin Solidity Unit Testing.

Si vous n’avez pas utilisé ce plugin auparavant et que vous ne voyez pas l’icône double check, vous devez l’activer depuis le gestionnaire de plugins Remix.

Allez dans le gestionnaire de plugins en cliquant sur l’icône (plug) et activez le plugin Solidity Unit Testing.

L’icône double check apparaît alors sur la barre d’icônes de gauche. En cliquant sur l’icône, le plugin sera chargé dans le panneau latéral.

Alternativement, sélectionnez simplement l’environnement Solidity depuis l’onglet Home de l’IDE Remix. Cela activera le plugin Solidity Unit Testing ainsi que les plugins Solidity Compiler, Deploy & Run Transactions et Solidity Static Analysis.

Après un chargement réussi, le plugin ressemble à ceci :

Répertoire des tests

Le plugin vous demande de fournir un répertoire qui sera votre espace de travail uniquement pour ce plugin. Pour sélectionner le répertoire, dès que vous ajoutez / au chemin, il affiche les options possibles.

Une fois sélectionné, ce répertoire sera utilisé pour charger les fichiers de test et pour stocker les fichiers de test nouvellement générés.

Le répertoire de test par défaut est browser/tests.

Générer

Sélectionnez un fichier solidity que vous voulez tester et cliquez sur le bouton Générer. Un fichier de test dédié au fichier sélectionné sera généré dans le répertoire de test.

Si aucun fichier n’est sélectionné, il créera quand même un fichier avec le nom générique newFile_test.sol.

Ce dossier contient suffisamment d’informations pour vous permettre de mieux comprendre l’élaboration de tests pour un contrat.

Le fichier générique se présente comme suit :

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");
    }
}

Rédiger des tests

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

Remix injecte une bibliothèque intégrée assert qui peut être utilisée pour les tests. Vous pouvez consulter la documentation de la bibliothèque here.

En outre, Remix permet d’utiliser certaines fonctions spéciales dans le fichier de test afin de rendre les tests plus structurés. Ces fonctions sont les suivantes :

  • 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

Pour commencer, consultez cet exemple simple.

Exécuter

Une fois que vous avez fini d’écrire les tests, sélectionnez le(s) fichier(s) et cliquez sur Run pour exécuter les tests. L’exécution se fera dans un environnement séparé. Après avoir terminé l’exécution d’un fichier, un résumé du test sera affiché comme ci-dessous :

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.

Arrêter

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.

Personnalisation

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

1. Contexte de compilation personnalisé

Solidity Unit Testing fait référence au plugin Solidity Compiler pour la configuration du compilateur. Configurez Compiler, EVM Version, Enable Optimization & runs dans le plugin Solidity Compiler et ceci sera utilisé dans le plugin Solidity Unit Testing pour la compilation des contrats avant de lancer les tests unitaires.

2. Contexte de transaction personnalisé

Pour interagir avec la méthode d’un contrat, les principaux paramètres d’une transaction sont l’adresse from, value et gas. Généralement, le comportement d’une méthode est testé avec différentes valeurs de ces paramètres.

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");
}

Mode d’emploi :

  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 doit être importé dans votre fichier de test pour utiliser le sender personnalisé

  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.

En ce qui concerne gas, Remix estime en interne le gaz nécessaire pour chaque transaction. Toujours si le déploiement d’un contrat échoue avec l’erreur Out-of-Gas, il essaie de le redéployer en doublant le gaz. Un déploiement qui échoue avec un gaz double affichera l’erreur suivante : le déploiement du contrat a échoué après avoir essayé deux fois : le code du contrat n'a pas pu être stocké, veuillez vérifier votre limite de gaz.

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.

  • Bien qu’un fichier de test qui importe remix_accounts.sol puisse ne pas compiler avec succès avec le plugin Solidity Compiler, ne vous inquiétez pas, cela n’aura aucune incidence sur son succès avec le plugin Solidity Unit Testing.