I've been learning how to write automated tests for a React app, and it's brought up questions on how best to test a series of interactions with the app.
Let's say that I have a React app that allows the user to assign students to seats in a classroom: Here's an image of what such an app would look like.
I'd like to test creating a new student, adding that student to a seat in the classroom, and then moving that student back to the area of unseated students in the middle column (I'll call it the roster).
What would be the best way to write out the test(s) for this? Would it make sense to have a single large test case, which would include assertions for each of the interactions I'm testing (creating a new student, moving it between the classroom and roster)?
Or should I create multiple cases, where one depends on the other? In other words...
Test 1) Check that a new student is created successfully when submitting the form
Test 2) Using the student created in test 1, move the student to a seat in the classroom
Test 3) With the student now in a seat (due to test 2), move it back to the roster area
Another question I have is whether React Test Library would be sufficient for this purpose. Or would this be considered an end-to-end test that should be written using Cypress?
Your feedback is much appreciated!
The process you described can surely be tested with react-testing-library as an integrated test. From the docs/faq, it encourages testing a component high enough up the component tree, without mocking child components, in order to simulate and test what an actual user interaction would be like.
Also check out this Kent C. Dodds blog post .
You want your tests to be as granular as possible, as you have already split them in 3 different cases. This will make it easier for everyone to read your code.
As for the testing library, I would go with Cypress which advertises itself as a JavaScript End to End Testing Framework.
You are testing end-to-end functionality here by manipulating what seem to be multiple components. React testing library, on the other hand, seems to focus on testing individual components on a more low-level approach - there's a chance it will falter on the long run, but it probably gets the job done aswell.
Related
I'm working with a team that has a project in Nightwatch.js. They are defining commands for almost everything:
Datetime functions as commands (return current day, array of days in a period, etc.)
SQL queries to get data as commands
To me, some of these fit better to utility classes, but they prefer to have them as commands, so they can access them via browser.Command.
What's the correct approach or recommendation? All in commands looks odd to me, but also the codes look more clean, as you don't need to do imports.
Thanks,
This question will probably get closed for being opinion based, but anyway.
I would agree that not all utilities should be commands. I would generally see the scope of command to be more to do with acting on things in the browser as the user would, or a way to group user actions, e.g. in a typical system I would see commands like -
login(), which would group the clicking into text fields and entering the username password and eventually clicking the login button.
addUser(), which would maybe be a small, but repetitive group of commands to add a user to an admin panel for example.
dragTo(x), which would maybe handle some drag and drop functionality.
etc.
I wouldn't see date utils etc as commands, but as you say, just utility functions, that are more about the underlying implementation of the test, and not how the user would interact with the system.
Although not Nightwatch, maybe take some advice from the Best Practices of Custom Commands from Cypress - https://docs.cypress.io/api/cypress-api/custom-commands#Best-Practices
Now I try to update webdriverio's maxInstances > 1 for our product automation test, but I cannot find a good way to make the different test instances use different user to run test. Sometimes different instances will use the same user to login, it will cause the first login instance session timeout.
Anybody knows how to lock/unlock user for this kind of scenario?
Let me get this straight: you are trying to run multiple instances, and have different parameters for each worker being spawned, right? (e.g: in your case use different, non-conflicting user accounts for the flows being run). Doesn't it seem like you zugzwang'ed yourself?
In theory, every test cases should have these three characteristics:
small
atomic
autonomous
❒ Possible solutions:
Wait for wdio-shared-store-service to be reviewed > approved > merged > released
This can take a week, or it can take a month, or several months. It might not even be a feature being shipped altogether as there was quite a lot of concern around being able to share data across checks (which people will eventually end up doing).
Currently there is not other functionality packaged inside the framework that will allow you to achieve the same outcome. If you are able to, maybe try to look for solutions by shifting the test approach.
Reorganise your testing logic:
have specific test accounts associated with specific checks (test cases) inside your feature files (test suites)
if you want to be extremely serious about your checks being atomic, then have each user account created for a specific test suite (as a test suite will only be run on one instance, per regression run)
organise your test suites as such that only specific user accounts will be used for a specific run, and make your runs specific: adding the -suite switch to your command
suites: {
user: [
'./test/features/user/AnalyticsChecks.js',
'./test/features/user/SitemapChecks.js'
],
superuser: [
'./test/features/superuser/HeaderChecks.js',
'./test/features/superuser/FooterChecks.js'
],
admin: [
'./test/features/admin/DropUserRoles.js',
'./test/features/admin/ClearCache.js'
],
batman: [
'./i/am/the/Darkness.js'
],
}
Create your users dynamically (pre-test, or during test run)
If you're lucky and have access to some backend calls to push users with specific configs to the DB (Ask for support from your Backend devs. Bring them candy!), then create a script that produces such users,
Alternatively, you can can create a custom_command that achieves the same. You call in your before/beforeEach hooks.
!Note: Don't forget to cleanup after yourself in the after/afterEach hooks.
Drawbacks:
contradicts the small principle
you won't be able to run them against PRODUCTION
you will probably be flagged by your backend for continuously polluting the DBs with new users (especially if you run 3-5 full regressions a day)
You can surely find a solution to remediate this framework limitation. Be creative. Everything goes. Cheers!
So this is more of a theoretical question rather than a programming question.
In my basic understanding of the Angular 4 framework a component can have inputs, outputs and services which also interact with the store to store data.
Now all of this, in the case of a web-app is displayed on a template. I have recently been looking at testing of such an app.
I plan to use Jasmine as the framework and Karma as the test runner on Chrome (for now).
With that said, what should I be testing for?
According to my understanding the basic tests should include some mock object handed to the component and checking if that is rendered properly on the template, mocking a service and checking what is rendered when we receive the correct response.
So what do I do after this? After I have tested this?
How is this behavior driven development? What can I do more?
What is a "good angular test"?
Since you have mensioned jasmine with karma, My perspective of answering this question will be mostly on Unit Testing. Let us go one question after another
What is a "good angular test"?
1) Unit testing should be written by the developer not by anyone else (tester).
2) It must have both positive and negative scenarios handled.
3) All network calls should be mocked or stubbed.
4) It should pass irrespective of environment.
5) It should have be easily readable, reliable and should not test the integration.
How is this behavior driven development? What can I do more?
In a nut shell BDD:
1) Write unit test cases prior to your development
2) Let all of your unit test cases fail
3) Start with your development unit by unit. Pass the assertion.
4) BDD is a advancement of TDD. In BDD we should not test the implementation but behavior should be tested.
5) BDD increases the code quality as well since we create test case based on behavior.
So what do I do after this? After I have tested this?
Current trend as explained above, after writing the test cases start with the development. Write the assertion, even the non technical person can understand the behavior.
You should also check if your bread-crumbs are in position, bread-crumbs are used for internal routing between pages. Also use the right path of your routing component in your app-module.
I recently finished up https://github.com/mercmobily/JsonRestStores. I feel a little uneasy as I haven't yet written any unit testing.
The module is tricky at best to test: it allows you to create Json REST stores, AND interact with the store using the API directly.
So, the unit test should:
Start a web server that implements a number of stores. Ideally, I should have one store for each tested feature I suppose
Test the results while manipulating that store, both using HTTP calls and direct API calls
The problem is that each store can have override a lot of functions. To make things more complicated, the store has a range of database drivers it can use (well, potentially -- at the moment I only have the MongoDB driver). So, wanting to test the module with MongoDB, I would have to first create a collection, and then test things using each DB layer...
I mean, it would be a pretty epic task. Can anybody shed some light on how to make something like this simpler? It seems to have all of the ingredients to make the Unit Testing from hell (API calls, direct calls, database, different configurable DB drivers, highly configurable class which encourages method overriding...)
Help?
You can write first the unit tests instead of start writing system tests
when you are going to add unit tests, you will need to learn mocking tests.
Backstory
I inherited a bunch of code that I'd like to refactor. It is a UI application written in javascript.
Current state:
We have main application which consist of several UI components. And each component has entry fields, textboxes, menus, etc), like "ticket", "customer information", etc. Based on input, where the application was called from, who is the user, we enable/disable, hide, show, change titles.
Unfortunately, the app grew to the point where it is really hard to scale, add new features. Main the driver (application code) calls set/unset functions of the respective components. So a lot of the stuff look like this
Main app unit
function1() {
**call_function2()**
component1.setX(true);
component1.setY(true);
component2.setX(false);
}
call_function2() {
// it may repeat some of the code function1 called
}
and we have a lot of this in the main union.
I am cleaning this mess. What is the best way to maintain the state of widgets?
Please let me know if you need me to clarify.
Looking at your code looks like you are accessing your view code directly from functions which as you correctly pointed is a bad idea. If you application is lot of GUI stuff then I would suggest you go with MVVM approach.
It would keep your view, binding and functionality completely separately. In future if you want to change the GUI, you can do it without touching any other classes.
Well I am not from JS background, but this is what my .Net exp says.