The Need for Fluent APIs
'Automation, automation, automation'. It seems to be one of the prevailing mottos of most agile projects I worked for. And rightly so, it makes perfect sense in the era of software and web revolution for us developers to write software that tests software. At the same time, automation brings a lot of value and enables teams to focus on continuous delivery of quality software.
Having said that, automation is never an easy business. Well, it might be easy (to an extent) to spin up a small automation project to test a few web pages, or unit or integration tests for relatively simple classes; however, it's not easy (in the sense that it requires developer traits, patterns and effort) to write maintainable, scalable and sharable automation code. Equally, it requires effort to write Fluent APIs - code that describes business and technical interactions in a human-readable fashion. But the result is worth it!
Developers = Craftsmen
Every agile software engineer should feel and act as a craftsman. As craftsmen, we endeavour to write maintanable and scalable code. And that applies both to production as well as testing code (whether integration, acceptance or unit). This is the main drive to write Fluent APIs.
Page objects or helper classes with hundreds of lines, or unsharabletest artifacts — these are some of the symptoms of automation projects which suffer and quite frequently are abandoned or even written from scratch...
At the same time, a lot of developers feel the need to de-couple the implementation of their automation from the test execution libraries they use (whether xUnit or BDD-style ones). In that way, they don't restrict themselves to one particular testing tool.
That's why we also want to avoid the 're-invention of the wheel' syndrome: It seems like a déjà vu experience; when you join a new project and you start creating services or tools to enable you perform your automation tasks quite so often, you find yourself copying or re-writing code you wrote in the past. And not only that - parts or whole packages of the classes you've authored, most of the times, can be useful to many more automators like yourself (e.g. connecting to databases and run stored procedures, fetching files from an SFTP location, creating a WebDriver factory, and so on, to name a few...). Admittedly, there are plenty of open source libraries which can help you specify your requirements (Cucumber, Specflow etc. etc.) or run web tests (e.g. Webdriver, Capybara etc.), but you have to write (or re-write) the boilerplate code yourself. It'd be good if we could share Actions and Capabilities, effectively Missions and Tools so as to reduce the need to clone github projects or extend existing classes...
Applying the Mission Pattern can be a means to assist you with all of the above. Let's see how:
The Mission Pattern: Main Concepts
a. The Agent
The Agent is the main entity that can you can use to perform Business and Technical tasks.
b. The Mission
The Mission is a set of Interactions with the System you want to test. It can optionally return a result. You can use Missions to create technical actions (e.g. ssh authentication to a server, selecting and materialising data from databases) or business actions.
c. The Tools
Tools are capabilities that the Agent obtains to perform Missions (e.g. a tool could be an instance of ChromeDriver, a Database tool or an instance of a bespoke client library useful to your tests, to name a few).
In More Detail
The Agent is the executor of missions by means of tools that enable him to interact with different layers of your system, or even external systems. In that way, you can perform end-to-end, acceptance and integration tests alike and at the same time create share-able Missions and Tools for your team to use or even other teams in your organisation; and that's feasible exactly because Missions are small, compact classes, focusing on a specific business or technical goal. They, then, fully abide by the 'Single-Responsibility-Principle'. The Agent applies the Visitor Pattern, so he is able to make use of his tools to orchestrate the execution of the missions we assign to him.
How To Apply It
As part of MagenTys we have created Cherry-JVM Framework (http://cherryframe.work). It is a micro-libraries framework enabling the application of Mission Pattern. In our documentation section we have a separate chapter with practical examples on how to write meaningful, share-able Missions and Tools in Java. Effectively, it's a canvas of tools helping developers to write their own Fluent APIs.
Let the code be fluent. Let there be Fluent APIs.