The surprising truth about success (and why some people never learn from their mistakes), is that it has everything to do with failure. Failure is not the opposite of success, it’s an essential part of it. It’s through failure, in a controlled and tested environment, that we learn and improve; a core principle of continuous delivery. Cloud-native technology speeds up the development cycle so that we can fail earlier and faster. But companies must also maintain quality, increase velocity and change the way they design and deliver their software to achieve a full cloud impact. This article explains how to do each of these three.
If failing is an essential part of success, then testing is the most important part of software development, especially acceptance testing. Acceptance testing not only closes the feedback loop in communication between business and IT, but it also ensures that the code “did what the business wanted it to do, in a production-like test environment,” as Dave Farley puts it. It can also be used as a “definition of ready” and “definition of done,” so, regardless of the application stack, acceptance testing applies.
NN Investment Partners (NNIP) recently began implementing cloud-native technology and achieved some success with building cloud-native serverless applications. They did their homework beforehand; reading blogs, attending conferences, and cloud-specific meetups. These are all great resources for gaining familiarity with the many benefits of the cloud. Unfortunately, these sources rarely discuss acceptance testing, so it’s unlikely that it’s applied when the technologies are subsequently put into practice.
NNIP knew that at some point they would have issues keeping their velocity up. The team’s advance awareness of these problems played a vital role in their success.
Introducing Automated Acceptance Testing within the Organization
Software engineers are the only ones who can break acceptance tests, so it stands to reason that they should also be responsible for them. In most companies, this means a culture change, but it’s also essential for continuous delivery and DevOps to work. Companies must enable software engineers to take responsibility by empowering them to create isolated production-like environments where than can test their software. If an organization has already made a separate team responsible for the infra stability, then they tend to find it difficult to empower software engineers with the responsibility to test their own software. This difficulty to switch between the two often results in a situation where engineers focus on failing and experimenting, while the infra-team remains focused on stability, causing a collision of goals, which in turn leads to a slow-down of the process.
Cloud native technology empowers teams to easily configure and create isolated, production-like environments on their own. This configuration is easily reused in different stages of the development process, from building applications locally, to asserting acceptance tests in a continuous delivery pipeline, to deploying to production. Once setup, software engineers can test every change to the software faster, without relying on other teams.
This new way of working required a new way of communicating. Engineers weren’t accustomed to using the business (domain) specific language to create and test requirements, because that was traditionally the task of the business analysts and QA team.
So, while the business was primarily concerned with whether or not the customer could see the right info, the engineers were wondering if the API got the correct data in the dynamoDB, or some other technology tool the business side had never heard of before. This created miscommunication and lack of understanding between different departments.
Introducing New Ways of Working
Organizations sometimes try to bridge the gap by introducing an agile way of working.What we need is a shared mind-set, or ubiquitous language in which we can safely communicate. Behaviour Driven Development (BDD), also known as ATDD, specification by example, and executable specifications, was created to bridge this gap. Learning (and thus failing) is the key here. Software development is a learning process; working code is a side effect.
For that reason, the first thing we as Xebia did at NNIP was to change the way refinements were held. Most refinements are subject to the "streetlight effect," a form of observational bias where we see only the positive results, or the easiest ones.To counter this effect, we need deliberate discovery, as opposed to accidental discovery. We want to discover as much as possible before going into a sprint with a certain user story. Finding new requirements during a sprint results in not finishing it, and decreases velocity. Even worse, we’ll build software that’s full of bugs, so of lower quality.
In his book, Specifications by Example, Gojko Adzic describes several practices you can use to battle the streetlight effect. One method is to describe input and outputs in concrete examples (or scenarios), because the human brain is far better at grasping abstract requirements that way.
The next step is to formalize these examples in the form of Gherkin scripts (feature files). These scripts form the basis of our automated (acceptance) tests, and give engineers the hands-on knowledge of building the right thing. The scripts provide the definition of “ready.” Without the scripts, we can’t begin building features.
To summarize, cloud-native technology gives companies the power to move faster towards DevOps and continuous delivery. It creates agile teams that include all the roles needed to quickly build and run software that the business needs.
Cloud native also creates new challenges, like the need for engineering to understand business and an ubiquitous scenario-based language to reduce bugs and increase code quality. Otherwise, the power of cloud-native technology is wasted.
This article is part of the Urgent Future report Cloud - It's a Golden Age.