Open tuliomir opened 2 years ago
Reviewers: @pedroferreira1 , @alexruzenhack
Does the Puppeteer work with the Electron?
It is possible to test UI without Puppeteer, we can use React Testing Library + Jest. Did you hear about this library? With this combo, the components can be rendered and navigated by DOM API and then asserted.
It is possible to test UI without Puppeteer, we can use React Testing Library + Jest. Did you hear about this library? With this combo, the components can be rendered and navigated by DOM API and then asserted.
Now I'm reviewing the PoC and see you use the React Testing Library already. Nice!
As such, possible paths for this UI test would be:
Update all react dependencies to use react-scripts@5 and try again
We've talked about trying to upgrade only the react-scripts and build a poc of one test suite using pupeteer, even if some parts of the app end up broken. Did you try to do it?
...we can use React Testing Library + Jest.
Added a Guide Level Description section documenting that these libs are being used on the PoC. :+1:
To avoid unnecessary consumption of HTR tokens, all tests should, at the end, melt every custom token generated to ensure the original HTR balance will be preserved - exception made for the NFTs that have a necessary fee. Those funds should finally be sent back to the source wallet to provide for future tests.
Why don't we run the tests using the testnet, so we don't really need to worry about losing funds?
Also have you validated how to run those tests using ledger? I know we have an emulator but not sure if they can be connected.
...have you validated how to run those tests using ledger?
Added considerations about the hardware wallet / ledger testing: they will be done in a future moment and are described on the Future Possibilities section.
...we don't really need to worry about losing funds?
About the amount of funds, while we have a lot of funds available on the testnet
, we also have to refill the funds on the source wallet manually. Since the tests are automated and may be executed very often, I think It's better to preserve these funds only to delay as much as possible the manual refilling process that will be done by the on-call.
What do you think?
Also, added a section on mocking and intercepting HTTP requests on the Future Possibilities section to cover a comment on the PoC PR.
About the amount of funds, while we have a lot of funds available on the testnet, we also have to refill the funds on the source wallet manually. Since the tests are automated and may be executed very often, I think It's better to preserve these funds only to delay as much as possible the manual refilling process that will be done by the on-call.
What do you think?
Yeah, this is good, I just think we should spend much time on that, especially when you say
It also would make it easier to change the values on some of the current QA tests to a fraction of what they are, so that fewer tokens are needed for each test iteration.
When we create a token, we need to create at least 1.00 amount to be able to melt and get the HTR deposit back. And even returning the tokens, it's always better to use testnet token and this was not mentioned in the design, that's why I wrote about it.
And this design is approved for me
Motivation
We currently spend many hours from the dev team running a QA process when we need to release a new version of the desktop wallet, or just validate that the wallet is working fine after a big refactor/change in the code.
Summary
We must have an easy way to automatically test the whole desktop wallet in order to decrease the time spent in QA's. The goal for this project is to create a design that will cover the full automated test cycle.
Acceptance Criteria
Guide-level description
Unit testing
Since we used the
create-react-app
helper to create this application, we already usejest
as a test framework.Following the recommendation from the main docs we will also use the
react-testing-library
as a set of testing helper APIs. It allows the test to easily:On the existing components' side, for a better testing procedure it's important to export each of them apart from its redux-connected default export, as shown on the
WalletAddress
component on the PoC ( commit diff ).End-to-end testing
The end-to-end testing is a way to run the application itself and interact with it simulating the user inputs. At the moment, the tests will be executed on the
testnet
, and as such the first interactions should set the server accordingly.The selected framework was Cypress, as it is one of the most popular and well-documented, because of its ease of implementation and use. The PoC has some bootstrap code to allow for a faster implementation later.
The testing scope for this design is the interaction with the Software Wallet only. Considerations about the Hardware Wallet testing are offered on the Future Possibilites section.
Funding of local test wallet
Since many of the tests require starting with an empty wallet and then adding tokens to it, it would be necessary to have a source for those funds. They will have to be transferred programatically at test run time and then used on the tests themselves.
To avoid unnecessary consumption of HTR tokens, all tests should, at the end, melt every custom token generated to ensure the original HTR balance will be preserved - exception made for the NFTs that have a necessary fee. Those funds should finally be sent back to the source wallet to provide for future tests.
It also would make it easier to change the values on some of the current QA tests to a fraction of what they are, so that fewer tokens are needed for each test iteration. These changes would make it harder for a human tester to identify the results, but is trivial for a machine-run test suite.
An alert should be raised at the
alerts-manager
whenever there are no funds available for the tests, so that the current on-call can provide the funds and the tests can be re-run.Sending funds for tests To send the funds, the ideal way is to import an existing wallet on the desktop wallet itself, using the Cypress interactions to do so. The wallet seed can be stored on a environment variable so that:
Once initialized, the test context itself will know the destination address to fund the newly created test wallet. After all the tests, the funds can be returned to the same source address.
PoC code
Available on PR #365
Rationale and Alternatives
Alternative framework: Puppeteer
At the moment, the main UI test frameworks available for javascript web apps are Puppeteer and Cypress.
Puppeteer is recognized as the most focused on programmatic testing — fitting for our GitHub CI workflow — while Cypress has more features focusing the interaction between Quality Assurance professionals and developers and some issues with breakpoint debugging.
After trying to implement it, some problems were found with the
react-scripts
dependency we currently have and this framework was discarded. Below are the steps taken and errors found while doing it.Manual script
A manual script to ensure Puppeteer interaction with the app was implemented: running the application using
npm run start
and then executing the script below shows that Puppeteer can connect with the application and read its state successfully.This can be done by simply running
npm install puppeteer --save-dev
before the script execution.However, once Jest is involved it inserts its own module resolver on the runtime flow. This breaks the interaction between the
puppeteer
module and its underlying libpuppeteer-core
. This is a known issue described on the Troubleshooting Guide.The errors found had variations of:
Troubleshooting Jest + Puppeteer
The solution offered was to update Jest, but the wallet desktop currently has no direct integration with Jest: it interacts with it only through the
react-scripts
lib. Updating it would require potentially a development effort that would not fit inside a proof of concept scope.Tentatives were made to:
As these paths failed, the amount of dependencies increased and all paths pointed to upgrading the jest version to v5, which is known to add more complex and application-wide necessary changes. So this path was discarded.
Possible paths for this framework would be:
react-scripts@5
and try againFuture possibilities
HTTP Interception and mocking
The main idea of the E2E tests are to validate the behavior of the application on a live network, so mocks and third-party call interceptions should be avoided whenever possible.
However, some tests may benefit from mocking, such as backend failure simulations. In these cases Cypress has a useful
intercept
tool that can both intercept the call and add a previously registered fixture as the response for that method.Ledger interaction
To test the interaction with a hardware wallet it's necessary to use an emulated device. The official Ledger Portal offers the following resources:
The current implementation of the desktop application, however, does not allow interaction with this emulated device because of the hardcoded transport layer package used (
@ledgerhq/hw-transport-node-hid
). A transport package should be used to communicate with the device simulator but it still needs an update by the Wallet Desktop's side, which would require another project dedicated to it.Task Breakdown
Unit testing done in 30,4 dev days on two main sections: Components and Screens E2E tests partially implementing the current QA process done in 13,1 dev days Total: 43,5 dev days
Components
Screens
QA Interactions
The objective here is to execute a series of steps as close as possible to the application's QA. Effort: 13.1 dev days
Task breakdown: Proposed approach
Start by the low-hanging fruits to allow for PRs that are shorter, simpler and faster to implement, review and deploy.
In this rationale, the suggested first week would have 3,6 estimated dev days. Future deploys would build upon existing code infrastructure and be easier to follow the development flow.