A phrase I’ve found myself using in various training sessions is “App as API”.
I think I’ve mentioned that in some previous blog posts but want to expand the concept here.
- Some applications provide an API
- Most applications provide a GUI
- Sometimes the API doesn’t do everything I want.
- Sometimes the functionality I want to use is only available from the GUI
So what do I do?
So I might have:
- create_user(name, username, password)
- login_user(username , password)
- change_password(username , new-password)
- create_project(username , project_name)
- has to delegate to an API abstraction since only the API allows me to create users
- I can login via the API or via the GUI and both return a valid session id, but only the GUI sets the session cookie so I start by using the GUI automation
- I can change password from the GUI and the API, so I pick the API
- the API doesn’t support creating projects so I use the GUI
Then I can’t create projects.
- inject projects directly into the database,
- but there is a risk of referential integrity issues and
- we have some sort of painful permissions process to gain write access to the database and yada yada yada the project admin is getting in the way.
What else could I do?
And what does that abstraction do?
Well, it sends HTTP requests to the backend when I fill in a form.
Therefore we could automate the sending of the HTTP requests, rather than automate the GUI?
And lo, we discover that it issues a number of HTTP requests:
- create a project
- add the user to the project
- create a default ‘context’
- add the context to the project
It also reveals a ‘risk’ at the GUI level we never knew about. What if only some of the requests make it through?
Perhaps that explains some of the referential integrity issues we’ve been encountering in the database when the system is used under high load?
“With great automating comes great responsibility and potentially increased risk” I think Peter Parker’s Uncle (tm, all rights reserved, fair usage clause invoked, no copyright violation intended) said something like that.
We have to take responsibility for the fact that we have automated this way.
- have code that uses the GUI library
- starts up a code controllable proxy e.g. (https://bmp.lightbody.net/)
- uses our “App as API” in “full GUI mode” to login and create a project
- as it does so, the requests are captured in the proxy
- we compare the requests the proxy captures with the requests we encoded in our API
- we assert that the requests are the same
Hey, as a side-effect, if we run this often, then we are also covering the risk that the GUI might not be able to create a project.
- We start to understand the application more
- We make our automated code less ‘in your face’ (i.e. no browsers popping up)
- We can use this to support our testing interaction with the app because the API is defined at a task level that we understand for testing rather than the API that the designer wanted to expose
- We identified risks that had gone unnoticed because we started testing at a more technical level
- And thousands of other benefits that we’ll realise over time (or we might not, the above might be enough)
In some cases we can easily automate the continual monitoring of those risks.
I often do this when I’m automating 3rd party applications because they either don’t give me an API or don’t expect an end user to want to do what I want to do.
I’ve used this on projects when the automated executions started taking too long, or failed because of ‘tool’ interaction issues.
And now you can experiment with your APP as an API.
Remembering that “with great… etc. etc.”