Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add option to run against live node #1172

Closed
wants to merge 30 commits into from

Conversation

iqdecay
Copy link
Contributor

@iqdecay iqdecay commented Oct 24, 2023

This PR adds a cargo feature called test-against-live-node, which enables running some test against a testnet node.

    let [wallet]: [WalletUnlocked; 1] = maybe_live_wallet(1)
        .await?
        .try_into()
        .expect("Vec can be converted to an array");
    setup_program_test!(
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );

Previously, this would have looked like this:

    setup_program_test!(
        Wallets("wallet"),
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );
  • This makes the code a little wordy but it's better than having to write the same tests twice.
  • I added a helper that generates up to 3 wallets connected to a testnet live node. The secret keys to these wallets are stored in github secrets.

Copy link
Contributor

@hal3e hal3e left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the devx improvement!

I have made some comments below on the current implementation. While I was testing it locally, I made a lot small changes so I added it to another branch. In the branch, RunOnLiveNode can be used without arguments and only one time etc. Branch: hal3e/test-against-live-node

Maybe it is worth to explore another implementation possibility. We could avoid adding a new command and instead rely on env variables. If the variable is set we can use beta wallets. So instead of checking if the command was used we could just use something like option_env! https://doc.rust-lang.org/stable/std/macro.option_env.html

Pseudo code:
in code_gen:

  • check if RUN_ON_LIVE_NODE env variable is Some("true") -> use beta wallets
  • else use random wallets

packages/fuels/tests/contracts.rs Outdated Show resolved Hide resolved
packages/fuels/tests/contracts.rs Outdated Show resolved Hide resolved
packages/fuels-test-helpers/src/node_types.rs Outdated Show resolved Hide resolved
@iqdecay
Copy link
Contributor Author

iqdecay commented Oct 26, 2023

@hal3e thanks a lot for your suggestion! I really like the idea of environment variables. However, we want to give the option to run only some relevant tests on the live nodes, first of all because it's slower, and potentially expensive. The env variables approach does not allow for this flexibility, as the pseudocode you wrote would apply each time we call setup_program_test which occurs >100 times in the codebase.

Thanks a lot for the branch, it's much better this way!

@hal3e
Copy link
Contributor

hal3e commented Oct 26, 2023

@hal3e thanks a lot for your suggestion! I really like the idea of environment variables. However, we want to give the option to run only some relevant tests on the live nodes, first of all because it's slower, and potentially expensive. The env variables approach does not allow for this flexibility, as the pseudocode you wrote would apply each time we call setup_program_test which occurs >100 times in the codebase.

Thanks a lot for the branch, it's much better this way!

That is a good point!

@iqdecay iqdecay force-pushed the iqdecay/test-against-live-node branch from 219c018 to ecccad2 Compare October 30, 2023 16:30
Copy link
Contributor

@segfault-magnet segfault-magnet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanly done!

I have one worry that I'd like to talk about:
setup_program_test besides being useful to us, is also marketed to users to help them bootstrap their tests quicker.

RunOnLiveNode isn't very flexible:

  1. You cannot say where the node is live at, an old beta? Some custom user node/network?
  2. It complicates the Wallets command. Previously it meant: "if a wallet is mentioned here I will setup the node and fund the wallet". Now it has a spin of "but if it is a live node, I will read ENV variables with some predetermined name format and connect to beta 4".

Currently, the following is possible without changes to the code:

User connecting to a node of his choice, with wallets of his choice:

    let provider = Provider::connect("my.provider.com").await?;
    let wallet = WalletUnlocked::new_from_private_key("private_key".parse().unwrap(), Some(provider))

    setup_program_test!(
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );

Us having a helper controlled by a feature:

async fn maybe_live_wallet() -> Result<WalletUnlocked> {
    if cfg!(feature = "live") {
        let provider = Provider::connect("my.provider.com").await?;
        Ok(WalletUnlocked::new_from_private_key(
            "private_key".parse().unwrap(),
            Some(provider),
        ))
    } else {
        launch_provider_and_get_wallet().await
    }
}

#[tokio::test]
async fn some_test() -> Result<()> {
    let wallet = maybe_live_wallet().await?;
    setup_program_test!(
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );

This way we can keep complexity out of the macro while still being able to achieve our live tests with one extra line.

@iqdecay
Copy link
Contributor Author

iqdecay commented Nov 1, 2023

I'm passing this PR as draft because it was supposed to be just a CI thing to test our repository against a live node, not a user-facing change. The CI thing cannot work until we solve #1180 and #1179.

@hal3e
Copy link
Contributor

hal3e commented Nov 1, 2023

Cleanly done!

I have one worry that I'd like to talk about: setup_program_test besides being useful to us, is also marketed to users to help them bootstrap their tests quicker.

RunOnLiveNode isn't very flexible:

1. You cannot say where the node is live at, an old beta? Some custom user node/network?

2. It complicates the `Wallets` command. Previously it meant: "if a wallet is mentioned here I will setup the node and fund the wallet". Now it has a spin of "but if it is a live node, I will read ENV variables with some predetermined name format and connect to beta 4".

Currently, the following is possible without changes to the code:

User connecting to a node of his choice, with wallets of his choice:

    let provider = Provider::connect("my.provider.com").await?;
    let wallet = WalletUnlocked::new_from_private_key("private_key".parse().unwrap(), Some(provider))

    setup_program_test!(
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );

Us having a helper controlled by a feature:

async fn maybe_live_wallet() -> Result<WalletUnlocked> {
    if cfg!(feature = "live") {
        let provider = Provider::connect("my.provider.com").await?;
        Ok(WalletUnlocked::new_from_private_key(
            "private_key".parse().unwrap(),
            Some(provider),
        ))
    } else {
        launch_provider_and_get_wallet().await
    }
}

#[tokio::test]
async fn some_test() -> Result<()> {
    let wallet = maybe_live_wallet().await?;
    setup_program_test!(
        Abigen(Contract(
            name = "TestContract",
            project = "packages/fuels/tests/contracts/contract_test"
        )),
        Deploy(
            name = "contract_instance",
            contract = "TestContract",
            wallet = "wallet"
        ),
    );

This way we can keep complexity out of the macro while still being able to achieve our live tests with one extra line.

I like this approach. As this is for our CI test only, a helper controlled with a flag seems to be the best solution.

@iqdecay iqdecay force-pushed the iqdecay/test-against-live-node branch 2 times, most recently from 0442b85 to 65e6007 Compare November 6, 2023 17:54
@iqdecay iqdecay force-pushed the iqdecay/test-against-live-node branch from 65e6007 to da4f61d Compare November 15, 2023 18:23
@iqdecay iqdecay marked this pull request as ready for review November 15, 2023 18:24
@iqdecay
Copy link
Contributor Author

iqdecay commented Nov 15, 2023

I have updated this PR to take into account the good suggestion by @segfault-magnet to make it a helper controlled by a feature flag.

@iqdecay
Copy link
Contributor Author

iqdecay commented Nov 25, 2023

Blocked notably by the fact that beta-4 is not compatible anymore, and there isn't a beta-5 node available yet.

@iqdecay
Copy link
Contributor Author

iqdecay commented Jan 19, 2024

Closing in favor of upcoming PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants