yevgenko
(Yevhen Viktorov)
August 11, 2018, 12:30am
1
Hi!
Iām trying to come up with efficient tests design for the full stack application which combines both client (web ui) and server in one, communicating via JSON API.
I come up with a sample app which is Ruby on Rails:
yevgenko:master
ā yevgenko:pay-with-tests
opened 04:23PM - 07 Aug 18 UTC
**tl;dr** The key difference comparing to common approaches is that we treat raiā¦ ls models as a resource documents and use them to assert both UI and API endpoints, without exposing serialization details (JSON Schema) into the tests. As a result it simplify tests, reduces coupling, duplication and expresses architecture.
## Problem
Most guides we can find online walks through every possible type of test that can be written for Rails.
They also comes with certain flaws, such as coupling to data structure (testing JSON).
With the raise of full-stack rich web applications, where frontend takes responsibility for managing requests and interpreting responses from server, the number of layers and testing tools increased by 2. Often we can see apps with tests for every part of MVC on server and MVC on client, plus some requests, plus features (end-to-end) and perhaps unit tests.
Yet with all that "coverage" there is often still big hole left in between client and server, i.e. communication protocol. It not as rare that JSON used to mock JavaScript tests went out of sync with actual JSON format used on backend. In a best cases it will be caught with end-to-end tests, and after some debugging and test updates (after syncing JSON) we can get back on track.
Multiply this by complexity of application and we will get pretty daunting picture.
Tons of tests walks through and asserting every edge of JSON schema there and here, yet struggle to keep it in sync.
All this comes down to the cost which takes to support such applications and I see it as an opportunity to make improvements.
## Objectives
* Explore Efficient Tests for Web Applications
* Tests that express architecture
* Avoid coupling to the data structure (i.e. JSON Schema)
* Make sample app
## Sample Web App
Introducing payments to Order Management Web App on Rails, with Backbone.js as frontend, and REST in between.
### Scenario
When app receives payment for order, it marks order as paid.
### UI
"Pay" button, makes request to API
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/assets/javascripts/orders.coffee#L17-L20
### REST API
creates "payments" resource
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/controllers/payments_controller.rb#L5-L9
### Domain
Order got an extra state "paid" and listens for payments,
it will transition to this state when payment resource created
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/models/payment.rb#L3-L9
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/models/order.rb#L8-L10
### Conventions
Rails views partials used to define JSON serialisation rules for resource objects, e.g. for payment resource it is `views/payments/_payment`
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/views/payments/_payment.json.jbuilder#L1
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/app/views/payments/create.json.jbuilder#L1
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/spec/support/rich_and_restful_tests/resource.rb#L22-L25
Resource abstraction supports models representation in tests and conform to [Responders](https://github.com/plataformatec/responders) conventions: https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/spec/support/rich_and_restful_tests/resource.rb#L2-L38
## Tests
### End To End
The goal, but also helps to establish infrastructure and define AR models.
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/spec/features/orders/payment_spec.rb#L3-L18
### UI
Guides towards routes, controller and JSON schema definitions.
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/spec/ui/orders/payment_spec.rb#L3-L24
### REST API
Guides implementation of resource endpoint, i.e. controller and model persistence.
https://github.com/yevgenko/rich-and-restful/blob/d97dccb7d51748826f111eff56925522d8e150f1/spec/api/orders/payment_spec.rb#L3-L17
## What missing?
* Handling errors and validations (API, UI and perhaps end-to-end)
* Integration tests for `payment` model `notifies order`
* Asynchronous assertions in application wrapper
And I keen to hear more from others experiences
Thanks.
yevgenko
(Yevhen Viktorov)
August 13, 2018, 4:51pm
2
tl;dr The key difference comparing to common approaches is that we treat rails models as a resource documents and use them to assert both UI and API endpoints, without exposing serialization details (JSON Schema) into the tests. As a result it simplify tests, reduces coupling, duplication and expresses architecture.