# Getting Started with Forge

By [crisgarner.eth](https://paragraph.com/@crisgarner) · 2022-01-12

---

Forge is a fast and flexible testing framework, inspired by [Dapp](https://github.com/dapphub/dapptools/tree/master/src/dapp). Part of the [Foundry toolkit](https://github.com/gakonst/foundry), a blazing fast, portable and modular kit for Ethereum development written in Rust.

### Why should you use it?

*   It’s really fast, no more wasted time while running tests.
    
*   Allows you to write tests in solidity which minimizes context switching.
    
*   A lot of testing features like fuzzing, console.log, and cheat codes give you more power and flexibility.
    
*   Non-standard directory structures support (works fine with Dapp or Hardhat repos).
    
*   Debugger and many more!
    

Installing Forge
----------------

As foundry is evolving fast and has a lot of contributors, the recommended way to install is using **foundryup** tool.

### Installing Foundryup

On Linux and macOS systems can be installed like:

    $ curl -L https://foundry.paradigm.xyz | bash
    

This command downloads **foundryup**. Then you can install foundry by running:

    $ foundryup
    

In Windows, you need to install it by building from the source.

### Building from source

First, you need to install rust, you can follow the official documentation here:

[https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install)

Then you can use cargo (the Rust package manager) to install foundry:

    $ cargo install --git https://github.com/gakonst/foundry --bins --locked
    

> As foundry is evolving fast with a lot of contributors it’s recommended to use [forgeup](https://github.com/transmissions11/forgeup) for managing various versions of Forge.

Initialize the Repository
-------------------------

Setup the folder that you want to use and initialize forge:

    $ mkdir my-app
    $ cd my-app
    $ forge init
    

This creates a simple project structure, you can of course configure it according to your needs, but for simplicity in this tutorial, I will use the default structure.

![](https://storage.googleapis.com/papyrus_images/280acc7fd2b8a2d56323da4011b5f4164130afd5ba735a496789fb9c67f5f57c.png)

### lib

The libraries that you install will go here, by default, _ds-test_ is installed, this one allows you to run tests, create asserts or logs. If you want to install other libraries you can run:

    $ forge install openzeppelin/openzeppelin-contracts
    

This will add the [openZeppelin repo](https://github.com/OpenZeppelin/openzeppelin-contracts) to lib/openzeppelin-contracts and you can use it with a simple import:

    import "openzeppelin-contracts/contracts/access/Ownable.sol";
    

> The path for the libs can be configured with remappings. _See_ **_Appendix B — Using Remappings_** _for further information._

### src

The src folder is where your contracts are. We are going to use this simple example to run a few tests:

    pragma solidity 0.8.10;
    
    contract Blacksmith {
      address public owner;
    
      constructor(address _owner){
        owner = _owner;
      }
    
      function onlyOwner() public{
        require(msg.sender == owner, "Not the owner");
      }
    }
    

### test

This is where your test lives, as a best practice, the test file is named exactly as the main contract with an appended _“.t”_, if your contract is named **blacksmith.sol** the test should be named **blacksmith.t.sol**.

> _We can define where the src and test folders are using environment variables. See_ **_Appendix A — Additional Resources_** _for further information._

How to Test
-----------

What makes a .sol file a test is inheriting from the DSTest library, which provides a complete list of assertions, equality checks, logs, and helpers that you can use. See the complete list on:

[https://github.com/dapphub/ds-test/blob/master/src/test.sol](https://github.com/dapphub/ds-test/blob/master/src/test.sol)

In order to run a test with forge you only need to use the command `forge test` . Use the following code and try it out:

    pragma solidity 0.8.10;
    
    import "ds-test/test.sol";
    import "../Blacksmith.sol";
    
    contract User {
      function callOnlyOwner(Blacksmith b) public {
        b.onlyOwner();
      }
    }
    
    contract BlacksmithTest is DSTest {
        Blacksmith blacksmith;
        User user;
    
        function setUp() public {
          blacksmith = new Blacksmith(address(this));
          user = new User();    
        }
    
        function testOwner() public {
            assertEq(blacksmith.owner(),address(this));
        }
    
        function testFailOwner() public {
           user.callOnlyOwner(blacksmith);
        }
    
        function testWrongOwner() public {
            user.callOnlyOwner(blacksmith); // This test will fail
        }
    }
    

Forge and Dapp use certain keywords in functions to run tests: setUp, test, and testFail.

**setUp()**

This function is called before each test or testFail function, perfect for initialization of contracts and additional setup.

**test\*()**

Functions that start with the keyword test will get run with forge and expect to _not revert_ in order to pass.

**testFail\*()**

Functions that start with the keyword test will get run with forge and expect to _revert_ in order to pass.

> Forge implements some cheat codes that make failing tests in a better way, we will cover the cheat codes in another tutorial.

* * *

_There is so much to cover with forge, but want to keep these tutorials short, will keep a small list of resources and tutorials updated in_ **_Appendix A — Additional Resources_**_. Feel free to share this article or contact me by sending a DM on Twitter_ [_@_**_Crisgarner_**](https://twitter.com/crisgarner)_._

### Appendix A — Additional Resources

*   [Getting Started With Forge by Wilson](https://w.mirror.xyz/mOUlpgkWA178HNUW7xR20TdbGRV6dMid7uChqxf9Z58) - Another getting started guide with useful information about verbosity, logging, traces, and fuzzing.
    

### Appendix B — Using Remappings

Remappings help when you want to use NPM style imports, or have a hardhat repo that installs their packages in `node_modules`, for example:

    import "@openzeppelin/contracts/access/Ownable.sol";
    

In order for Forge to know where to find this dependency you need to create a `remappings.txt` file at the top level of your project directory. So the steps you need to follow are:

1.  `forge install openzeppelin/openzeppelin-contracts` (this will add the repo to `lib/openzepplin-contracts`)
    
2.  Create a remappings file: `touch remappings.txt`
    
3.  Add this line to `remappings.txt`
    

    @openzeppelin/=lib/openzeppelin-contracts/

---

*Originally published on [crisgarner.eth](https://paragraph.com/@crisgarner/getting-started-with-forge)*
