Skip to content

Commit

Permalink
feat: Add support for calling into contract ABIs from unit tests (#3672)
Browse files Browse the repository at this point in the history
closes #3262.

# About this PR

For unit tests in contracts, we are now deploying the contract before
executing the tests so that we can support calling into contract ABI.

With this PR testing a contract looks like:

1. Compile the contract with tests
2. Compile the contract without the tests
3. Deploy the contract (the one that we compiled without the tests)
4. Run each test as a script

Currently there is no way to obtain the contract id without deploying
the contract (related #3444) and automatic `CONTRACT_ID` injection is
not available as we cannot inject it until we solve #3622.

~I am planning to tackle #3622 and add the documentation after that as
this is not directly usable by our users until we have `CONTRACT_ID`
injection or #3444.~
I changed my mind and decided to print the contract id for now so that
this will be useable and because of that I will be adding the
documentation with this PR.

For now it the testing flow will be rough as users will need to first
run `forc test` and get the contract id and manually edit their tests
while setting up the tests (writing the `abi` casts). I will add some
explanation of the process and point to #3673 since it will make the
testing flow seamless.

## TODO

- [x] Add tests
- [x]  Add documentation
  • Loading branch information
kayagokalp committed Jan 4, 2023
1 parent 09474ad commit 7552b58
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 80 deletions.
43 changes: 40 additions & 3 deletions docs/book/src/testing/unit-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,44 @@ Tests with `#[test(should_revert)]` considered to be passing if they are reverti

## Calling Contracts

***Coming Soon***
Unit tests can call contract functions an example for such calls can be seen below.

*Track progress on constract calls in tests
[here](https://github.com/FuelLabs/sway/issues/3262)*
```sway
contract;
abi MyContract {
fn test_function() -> bool;
}
impl MyContract for Contract {
fn test_function() -> bool {
true
}
}
```

To test the `test_function()`, a unit test like the following can be written.

```sway
#[test]
fn test_success() {
let contract_id = 0xa8f18533afc18453323bdf17c83750c556916ab183daacf46d7a8d3c633a40ee;
let caller = abi(MyContract, contract_id);
let result = caller.test_function {}();
assert(result == true)
}
```

It is also possible to test failure with contract calls as well.

```sway
#[test(should_revert)]
fn test_fail() {
let contract_id = 0xa8f18533afc18453323bdf17c83750c556916ab183daacf46d7a8d3c633a40ee;
let caller = abi(MyContract, contract_id);
let result = caller.test_function {}();
assert(result == false)
}
```

> **Note:** `contract_id` is needed for the `abi` cast used in the test. Running `forc test` will output deployed contract's id and that can be used for the cast. This means, before writing the `test_success()` test, `forc test` needs to be executed to retrieve the `contract_id`. This will not be necessary in the future and you can track the progress at [here](https://github.com/FuelLabs/sway/issues/3673).
14 changes: 12 additions & 2 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub struct BuiltPackage {
source_map: SourceMap,
pub pkg_name: String,
pub declaration_engine: DeclarationEngine,
pub manifest_file: PackageManifestFile,
}

/// The result of successfully compiling a workspace.
Expand Down Expand Up @@ -255,7 +256,7 @@ pub struct GitSourceIndex {
pub head_with_time: HeadWithTime,
}

#[derive(Default)]
#[derive(Default, Clone)]
pub struct PkgOpts {
/// Path to the project, if not specified, current working directory will be used.
pub path: Option<String>,
Expand All @@ -273,7 +274,7 @@ pub struct PkgOpts {
pub output_directory: Option<String>,
}

#[derive(Default)]
#[derive(Default, Clone)]
pub struct PrintOpts {
/// Print the generated Sway AST (Abstract Syntax Tree).
pub ast: bool,
Expand Down Expand Up @@ -434,6 +435,14 @@ impl Built {
Built::Workspace(built_workspace) => Ok(built_workspace),
}
}

/// Tries to retrieve the `Built` as a `BuiltPackage`, panics otherwise.
pub fn expect_pkg(self) -> Result<BuiltPackage> {
match self {
Built::Package(built_pkg) => Ok(*built_pkg),
Built::Workspace(_) => bail!("expected `Built` to be `Built::Package`"),
}
}
}
const DEFAULT_REMOTE_NAME: &str = "origin";

Expand Down Expand Up @@ -2406,6 +2415,7 @@ pub fn compile(
source_map: source_map.to_owned(),
pkg_name: pkg.name.clone(),
declaration_engine: engines.de().clone(),
manifest_file: manifest.clone(),
};
Ok((built_package, namespace))
}
Expand Down

0 comments on commit 7552b58

Please sign in to comment.