# Testing Guide

## Testing with Truffle <a href="#testing-with-truffle" id="testing-with-truffle"></a>

Truffle provides an automated testing framework. This framework lets you write simple and manageable tests in two different ways:

* In `Javascript` and `TypeScript`, for exercising your contracts from the outside world, just like application.
* In `Solidity`, for exercising your contracts in advances, bare-to-the-metal scenarios.

### 1) Get Started

Add a setter function `setGreet` to the contract for testing purpose. The source code is given below.

```solidity
pragma solidity ^0.5.6;
contract Mortal {
    /* Define variable owner of the type address */
    address payable owner;
    /* This function is executed at initialization and sets the owner of the contract */
    constructor () public { owner = msg.sender; }
    /* Function to recover the funds on the contract */
    function kill() public payable { if (msg.sender == owner) selfdestruct(owner); }
}

contract MEVerseGreeter is Mortal {
    /* Define variable greeting of the type string */
    string greeting;
    /* This runs when the contract is executed */
    constructor (string memory _greeting) public {
        greeting = _greeting;
    }
    /* Main function */
    function greet() public view returns (string memory) {
        return greeting;
    }

    /* Newly added function for testing. */
    function setGreet(string memory _greeting) public {
        // only owner can change greeting message
        require(msg.sender == owner, "Only owner is allowed.");
        greeting = _greeting;
    }
}
```

**Test Scenario**&#x20;

1. Whether `greet()` function returns  "Hello, MEVerse" properly
2. Whether `setGreet()` function returns new greeting message properly and reverts when non-owner account attempts to update the greeting.

First, we will install the Chai assertions library (or any different assertions library you use) for generic assertions, and the truffle-assertions library for the smart contract assertions.

```shell
npm install --save-dev chai truffle-assertions
```

### 2) Writing test in Solidity <a href="#id-2-writing-test-in-solidity" id="id-2-writing-test-in-solidity"></a>

Testing with Solidity can be a little bit more intuitive than JavaScript tests. Solidity test contracts live alongside JavaScript tests as .sol files.

Create a file called `TestMEVerseGreeting.sol`  in the `test` folder. The Truffle suite provides helper libraries for testing, so let's take a look at the example Solidity test:

```solidity
pragma solidity ^0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/HashMarket.sol";
```

* DeployedAddresses : Every time you change your contract, you must redeploy it to a new address. You can get the deployed contract addresses through this library.
* Assert : It gives us access to various testing functions, like `Assert.equals()`, `Assert.greaterThan()`, etc.

```solidity
pragma solidity ^0.5.6;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MEVerseGreeter.sol";

contract TestMEVerseGreeting {

    function testGreetingMessage() public {
        // DeployedAddresses.MEVerseGreeter() handles contract address.
        MEVerseGreeter greeter = MEVerseGreeter(DeployedAddresses.MEVerseGreeter());

        string memory expectedGreet = "Hello MEVerse";

        string memory greet = greeter.greet();

        Assert.equal(greet, expectedGreet, "greeting message should match");
    }
}
```

Run Solidity test code

```shell
$ truffle test
Using network 'test'.


Compiling your contracts...
===========================
> Compiling ./test/TestMEVerseGreeting.sol
> Artifacts written to /var/folders/8k/pj9b6lld4qn4hq1l7h97y9pm0000gn/T/test--5158-mS50YzRSpyUZ
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



  TestMEVerseGreeting
    1) testGreetingMessage
    > No events were emitted


  0 passing (3s)
  1 failing

  1) TestMEVerseGreeting
       testGreetingMessage:
     Error: greeting message should match (Tested: Hello, MEVerse, Against: Hello MEVerse)
      at checkResultForFailure (/Users/meverselabs/.nvm/versions/node/v16.16.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/testing/SolidityTest.js:66:1)
      at runMicrotasks (<anonymous>)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at Context.<anonymous> (/Users/meverselabs/.nvm/versions/node/v16.16.0/lib/node_modules/truffle/build/webpack:/packages/core/lib/testing/SolidityTest.js:92:1)
```

It failed. Let's take a look at the error message.

`Error: greeting message should match (Tested: Hello, MEVerse, Against: Hello MEVerse)`

Notice the missed `',(comma)'` at *string memory expectedGreet = "Hello MEVerse"*.\
Fix the code and run the test again.

<pre class="language-shell"><code class="lang-shell"><strong>$ truffle test
</strong>Using network 'test'.


Compiling your contracts...
===========================
> Compiling ./test/TestMEVerseGreeting.sol
> Artifacts written to /var/folders/8k/pj9b6lld4qn4hq1l7h97y9pm0000gn/T/test--5231-DBNS4Mgo7Mo0
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



  TestMEVerseGreeting
    ✓ testGreetingMessage (41ms)


  1 passing (3s)
</code></pre>

Test success!

If you want to test your contract on Testnet, use `network` option.

```shell
$ truffle test -network MEVerseTestnet
Using network 'test'.


Compiling your contracts...
===========================
> Compiling ./contracts/MEVerseGreeter.sol
> Compiling ./test/TestMEVerseGreeting.sol
> Artifacts written to /var/folders/8k/pj9b6lld4qn4hq1l7h97y9pm0000gn/T/test--5324-jtF8M5Qz82cV
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



  TestMEVerseGreeting
    ✓ testGreetingMessage (55ms)


  1 passing (3s)
```

### 3) Writing test in JavaScript <a href="#id-3-writing-test-in-javascript" id="id-3-writing-test-in-javascript"></a>

Truffle uses the [Mocha](https://mochajs.org/) testing framework and [Chai](https://www.chaijs.com/) assertion library to provide a solid framework for JavaScript test. JavaScript test gives you more flexibility and enables you to write more complex tests.

Let's create a file and name it `0_MEVerseGreeting.js` under `test` directory.\
The test code is:

```javascript
// Interacting directly with MEVerseGreeter contract
const MEVerseGreeter = artifacts.require("./MEVerseGreeter.sol");
const truffleAssert = require('truffle-assertions');

contract("MEVerseGreeter", async(accounts) => {
    // store the contract instance at a higher level 
    // to enable access from all functions.
    var MEVerseGreeterInstance;
    var owner = accounts[0];
    var greetMsg = "Hello, MEVerse";

    // This will run before each test proceed.
    before(async function() {
        // set contract instance into a variable
        MEVerseGreeterInstance = await MEVerseGreeter.new(greetMsg, {from:owner});
    })

    it("#1 check Greeting message", async function() {
        // set the expected greeting message
        var expectedGreeting = greetMsg;
        var greet= await MEVerseGreeterInstance.greet();
        assert.equal(expectedGreeting, greet, "greeting message should match");

    })

    it("#2 update greeting message.", async function() {
        var newGreeting = "Hi, MEVerse";

        await MEVerseGreeterInstance.setGreet(newGreeting, { from:owner });
        var greet = await MEVerseGreeterInstance.greet();
        assert.equal(newGreeting, greet, "greeting message should match");
    });

    it("#3 [Failure test] Only owner can change greeting.", async function() {
        var fakeOwner = accounts[1];        
        await truffleAssert.fails(MEVerseGreeterInstance.setGreet(greetMsg, { from:fakeOwner }));
    });
});
```

Run test file `0_MEVerseGreeting.js`)

<pre class="language-shell"><code class="lang-shell"><strong>$ truffle test ./test/0_MEVerseGreeting.js
</strong>Using network 'test'.


Compiling your contracts...
===========================
> Compiling ./contracts/MEVerseGreeter.sol
> Artifacts written to /var/folders/8k/pj9b6lld4qn4hq1l7h97y9pm0000gn/T/test--5527-DYxpp0UInYnm
> Compiled successfully using:
   - solc: 0.5.16+commit.9c3226ce.Emscripten.clang



  Contract: MEVerseGreeter
    ✓ #1 check Greeting message
    ✓ #2 update greeting message. (42ms)
    ✓ #3 [Failure test] Only owner can change greeting. (176ms)


  3 passing (301ms)
</code></pre>

For more details, please check [Truffle testing](https://www.trufflesuite.com/docs/truffle/testing/testing-your-contracts) and [Truffle commands](https://www.trufflesuite.com/docs/truffle/reference/truffle-commands#test) for details.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://meversedex.gitbook.io/meverse-dev-docs/smart-contract/testing-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
