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

Auto tests #45

Closed
wants to merge 8 commits into from
Closed

Auto tests #45

wants to merge 8 commits into from

Conversation

mariopil
Copy link
Member

@mariopil mariopil commented Aug 25, 2023

Referenced issue
Closes #34

Summary of changes
Here's a simple node.js tool for automated contract tests. What it does:

  • creates accounts
  • funds them using friendbot
  • deploys a contract
  • runs its methods according to prepared scenario
  • checks results and calculates fees

To run it call npm run tests. You can specify which tests to run, e.g. npm run tests voting. If any of the test fails, tool will exit with -1 code. Tool could be added to GitHub jobs as an action run after each commit.

Each contract has its separate ts code with the test scenario. To add new test for a new contract just create new ts file, extend the BaseTests class and update TestsRunner class.

The Raffle test is not completed yet, as the contract fails on futurenet.

Reviewer recommendations

How to make the review easier. i.e "Its a big PR and the recommendation is to go through each commit"
or "In order to run the tests, execute ..."

@mariopil mariopil self-assigned this Aug 25, 2023
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this file needed?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, I'll remove it.

Copy link
Contributor

@geofmureithi geofmureithi left a comment

Choose a reason for hiding this comment

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

I have left some thoughts on the API.
Let me know what you think.

}
},
error => {
resultOk = false
Copy link
Contributor

Choose a reason for hiding this comment

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

This continues executing even if the result is false. Why not use Promises.all

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, we may want to introspect when something fails, so we might prefer to use Promises.allSettled

this.contractId = data.toString().trim()
},
error => {
result = false
Copy link
Contributor

Choose a reason for hiding this comment

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

Just return the promise and handle the result upstream

}

async getTokenId() {
let resultOk = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, return the promise itself instead of bool

}

async invokeBuyTickets() {
let resultOk = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here with Promises.all

}

async invokePlayRaffle() {
let resultOk = true
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

await this.calculateFeesForAccount('player_1')
}

public async run(): Promise<boolean> {
Copy link
Contributor

Choose a reason for hiding this comment

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

If these methods return promises then you can do:

this.createAccounts()
   .then(res => this.deployContract('voting'))
   .then(......)
   .catch((e) => ... )

const test = this.tests.get(testName)
if (test === undefined) {
console.error(`Could not find test ${testName}`)
--testsToRun
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
--testsToRun
throw new Error(`Could not find test ${testName}`)

Copy link
Member Author

Choose a reason for hiding this comment

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

That would cause the app to exit which I don't want. Let it still continue with other found tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the problem inherently comes from having a custom test runner.
Have you considered something like TestRunner?
It would help run tests per file, this gives the person running tests ability to control what someone runs.
WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

I have not. Will take a look at it later. The implemented test runner is very simple and I'm not sure there's any need to change it or make it more complex :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you are reinventing the wheel.
Eg I can't run a single test with the current implementation, I have to run all or change the code.
Test runner comes bundled with node and is well documented and tested. I don't think that is complexity as compared to having to reference a custom impl. The changes requested are not major, you just have to wrap the calls eg:

test('Raffle Contract', async (t) => {
  await t.test('init' , (t) => {
    assert.strictEqual(1, 1);
  });

  await t.test('create_proposal;', (t) => {
    assert.strictEqual(2, 2);
  });
}); 

Now:

  • I can run each file alone.
  • The test runner manages what fails etc.
  • The test runner can output other file formats if needed.

If you are not into working on it, I can do it because I don't feel ok with the current impl.

Copy link
Member Author

Choose a reason for hiding this comment

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

There's nothing more to manage than in the example you've posted. You still have to write at least the same amount of code. I don't see a value added here.

Copy link
Contributor

@geofmureithi geofmureithi Aug 25, 2023

Choose a reason for hiding this comment

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

I think I disagree with the notion that it adds no value.
First of all we wouldn't have the testrunner file, secondly when adding new contracts we don't need to declare a new contract in code, just add the file and it runs.
We plan to have up to 10 contracts, I think I see a lot of value in this.
I can do a PR with the changes I am recommending if need be.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, feel free to add it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please see #47

Copy link
Member

Choose a reason for hiding this comment

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

I think this is a tool we should prepare for external use. I see both POVs. But i think the developer experience will be better with a well known test runner. Also this test runners normally have the possiblity of multiple output formats, which can be used later in a miriad of ways :)

@geofmureithi
Copy link
Contributor

Are these tests run by CI?

import configJson from './config.json'

export class AppConfig {
public friendbot: string = ''
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public friendbot: string = ''
public friendbot: string = configJson.server.friendbot;

Is this possible? We would not need the parseConfig().

Copy link
Member

@eloylp eloylp left a comment

Choose a reason for hiding this comment

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

Hello ! thanks for PR description. I am still reading the code in detail, just providing early feedback here:

  • Would it be good to add a README.md inside the test folder, indicating what does this tool and some examples ? Imagine someone with no context lands in that folder, what would be useful ? Also, should we point to this README.md from the root one ?

  • Its sad we cannot implement this in Rust to be honest, taking into account we are targeting Soroban smart contracts (i know, nothing to do with contracts themselves, but the community writes things in rust). I would like to know how far we would be from this and what we would need from Soroban to implement/fix. Maybe its something doable to open an upstream issue :)

@vercel
Copy link

vercel bot commented Aug 29, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
eiger-nebula ❌ Failed (Inspect) Aug 29, 2023 7:58am

@mariopil
Copy link
Member Author

mariopil commented Sep 14, 2023

Should we close this PR without merging now when the cargo make tool will be used for integration tests?

@geofmureithi
Copy link
Contributor

Lets close this one.

@mariopil mariopil closed this Sep 18, 2023
@mariopil
Copy link
Member Author

There is another automated tests tool written using cargo make . This one is not needed anymore.

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

Successfully merging this pull request may close these issues.

E2E testing tools for Soroban contracts
3 participants