Testing at both ends of the triangle

Testing at both ends of the triangle

About

Derek Graham is a Principal Developer for Sage and runs NEBytes and spoke about Cypress for Tech on the Tyne.

The Testing Triangle

Is a metaphor of the types and proportions we should have in the project from Unit Tests, Integration Tests and end-to-end tests with increasing integration and complexity towards the top of the pyramid but with fewer of them but are more complex. Unit Tests are quick to right and give good feedback and give this feedback quickly.

Test code is code - Code that is as simple as possible to write, it is also the code we don't test.

Microtests - these are something that are meant to give precise feedback about a small chunk of the code such as single function or class, don't separate things out for the sake of it. Unit Tests is not a unit test if it talks to database, network filesystem or can't be run at the same time as other unit tests.

End-to-end tests - Take longer to write, change and debug and they tend to be slower and fail for more reasons but check that your application is wired together correctly. You might have a webserver so may need to have configuration and database which can be the worst kind of thing to test as has to be in the right place and have right data and be kept up-to-date.

Integration tests in the middle is where you tend to have the worst trouble, longer to run than unit tests and prone to breakage by changes to the application. They can often be used to test too large a piece of functionality. You might have a fake API and database and might not know which is which but might not have enough context but might also have too much about the system in the test, they also require much more maintenance can also check out J B Rainsberger video about Integration Tests are a Scam.

Both ends of the Triangle

Lots of microtests at the bottom, as isolated as possible where each thing works and at the top everything is wired right and have maximum realism with nothing in the middle. Derek has written websites many years ago and have done testing using Powershell to make the web requests and check if the links work in their website but didn't check if they rendered. Later they had more web projects that need more testing they converted lots of Word HTML along with the NEBytes website to Eleventy instead but needed tests to be able to make sure this worked correctly using Cypress.

Cypress

Productive and easy to use than a lot of web testing products and can be used with JavaScript, makes tests easy to write and reason about compared to Selenium tests in C#. Have good documentation at docs.cypress.io and can also debug or log during tests when needed.

Good Things

Cypress “runs” inside the browser, automatic waiting once something has happened, debuggability, takes snapshots so can step through what the test is doing, spies where you can spy on event handlers. You can also do network interception so don't have to do network requests and fake those out and component doesn't need to know about that, it takes screenshots and videos so if something fails you can have a look at the screenshots or video and see what it did. It also supports hot reload and if you change a test, it will run it again along with automatic retry as it understands what the browser is doing it will wait for things to be displayed in the browser and take away things you don't want to be dealing with.

Bad Things

Doesn't support multiple tabs, not as established as Selenium, JavaScript online, doesn't support Safari and iframes support is limited. Multi-site is not allowed although there is an origin command so can sign into something where get taken to another auth provider and then when come back do the tests again. Login is still an issue if have a website that is authenticated with another provider and this is seen first Cypress will see this as your website and can be difficult to work with but this may be resolved in a future version.

Jest

Jest is another test library which will run tests in rspec format and can describe something then have the tests themselves that are actually running. Jest is one of the more popular frameworks for testing where can see if something happens and see what is expected and if something doesn't happen the test will fail.

Writing Cypress Tests

All files begin with cy.* and you can chain commands together with a fluent style of writing tests. E2E tests can be picked up fairly easily and Cypress will find whatever tests there are and will run them for you, extension needs to be .cy.js for them to be found.

Arrange, Act & Assert

Arrange - Arranging things would be to visit a website, it will either fire up a browser and won't return until the page has loaded, you can also do tiding up before doing any tests such as clearing local storage by using the event “before” which is triggered before a test is run to do this or can do “beforeEach” which will happen before each test and there is also “after” and “afterEach”.

Act - You can get Cypress to get a control by id, class or X-path expression. You can find elements with data-cy-attributes which is the most reliable, visible text although this can change, element ids, class names but the markup can change, and these can be changed from what was intended or use a generic control name such as button or link as could have many items and could return a random item. Get will wait for something to be on screen within four seconds.

Assert - You can check if something contains a value, this can also use matchCase if don't want this to be case-sensitive, you can get fields and see if they don't contain a value, or a set of values. You don't have to add delays to get values as Cypress will wait correctly.

Should - All assertions live with this or can check things with be.visible, have.attr, have.value, have.text and not.exist to see that something shouldn't be there which doesn't require a delay.

Component Tests

These are new to Cypress and can sandbox components such as those in React or Vue, you don't need to run the whole application and the component can be tested and it won't know that it is not in a real webpage. Can have component level tests, sandboxes, with time travel and have before and after with the same developer experience as the end-to-end tests and can get an example for a Calendar.

Its & Invoke

If there is something you can't get access to for Its for properties of objects and invoke for functions on objects, so you can use this to look at session storage in the browser, or redux store and even dispatch objects to redux that a component might be reading.

Custom Commands

In the support folder you can add your own commands such as reading data from storage, so these are methods that can invoke the functionality you need within your tests and minimise the amount of code that is needed in the tests and re-use functionality across tests.

Spies & Stubs

You can inspect how often something has been called and can stub out methods where needed. With spy you could monitor if something was clicked and stub allows you to substitute a function to mock some behaviour in the test where needed.