> For the complete documentation index, see [llms.txt](https://docs.phron.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.phron.ai/developers/build-with-phronai/smart-contracts-development/solidity-contracts/phron-api/testing.md).

# Testing

#### Writing Unit Tests

Unit tests are essential to ensure your smart contract behaves correctly. Using **Mocha** and **Chai** in conjunction with **Hardhat** provides a robust framework for testing your Solidity contracts.

**Install Mocha/Chai**

To set up testing, install the required libraries:

```bash
npm install --save-dev mocha chai
```

***

#### Example Test Suite: Token Contract

Here's an improved example of a test suite for a token contract:

{% code overflow="wrap" %}

```javascript
const { expect } = require("chai");

describe("Token Contract", function () {
    let Token, token, owner, addr1, addr2;

    // Before each test, deploy a new token contract instance
    beforeEach(async function () {
        [owner, addr1, addr2] = await ethers.getSigners(); // Retrieve test accounts
        Token = await ethers.getContractFactory("MyToken");
        token = await Token.deploy(); // Deploy the contract
    });

    describe("Deployment", function () {
        it("Should set the correct owner", async function () {
            expect(await token.owner()).to.equal(owner.address);
        });

        it("Should assign the total supply of tokens to the owner", async function () {
            const ownerBalance = await token.balanceOf(owner.address);
            expect(await token.totalSupply()).to.equal(ownerBalance);
        });
    });

    describe("Transactions", function () {
        it("Should transfer tokens between accounts", async function () {
            // Transfer 50 tokens from owner to addr1
            await token.transfer(addr1.address, 50);
            const addr1Balance = await token.balanceOf(addr1.address);
            expect(addr1Balance).to.equal(50);
        });

        it("Should fail if sender doesn’t have enough tokens", async function () {
            const initialOwnerBalance = await token.balanceOf(owner.address);

            // Attempt to transfer 1 token from addr1 (has 0 tokens) to addr2
            await expect(
                token.connect(addr1).transfer(addr2.address, 1)
            ).to.be.revertedWith("Insufficient balance");

            // Ensure owner's balance remains unchanged
            expect(await token.balanceOf(owner.address)).to.equal(initialOwnerBalance);
        });

        it("Should update balances after transfers", async function () {
            const initialOwnerBalance = await token.balanceOf(owner.address);

            // Transfer 100 tokens from owner to addr1
            await token.transfer(addr1.address, 100);

            // Transfer 50 tokens from addr1 to addr2
            await token.connect(addr1).transfer(addr2.address, 50);

            const finalOwnerBalance = await token.balanceOf(owner.address);
            expect(finalOwnerBalance).to.equal(initialOwnerBalance - 100);

            const addr1Balance = await token.balanceOf(addr1.address);
            expect(addr1Balance).to.equal(50);

            const addr2Balance = await token.balanceOf(addr2.address);
            expect(addr2Balance).to.equal(50);
        });
    });
});
```

{% endcode %}

#### Breakdown of the Test Cases:

1. **Deployment Tests**:
   * **Ownership**: Verifies that the contract's owner is correctly assigned upon deployment.
   * **Initial Token Distribution**: Confirms that the contract assigns the total token supply to the owner's balance.
2. **Transaction Tests**:
   * **Successful Transfers**: Verifies that tokens can be transferred from one account to another and the balances are updated correctly.
   * **Failed Transfers**: Ensures that a transfer will fail if the sender doesn't have enough tokens, reverting the transaction.
   * **Balance Updates**: Checks that the balances are correctly updated after multiple transactions.

#### Running the Tests

To run the test suite, use the following command:

```bash
npx hardhat test
```

This will execute all test cases and display the results, ensuring that your contract behaves as expected under various conditions.

#### Improvements in this Version:

* **Modular Tests**: Divided tests into logical groups (e.g., `Deployment` and `Transactions`) for better organization and readability.
* **Edge Case Testing**: Added test cases for failure conditions (like insufficient balances) to ensure that your contract handles errors correctly.
* **Reusability**: Used `beforeEach` to deploy a fresh contract instance for each test, ensuring isolation between test cases and preventing state leakage.

This structure makes the tests more maintainable and easier to extend as your contract grows.
