Wednesday, 12 December 2018

How to advance your test automation skills with source control

Image result for source control meme

If you're a tester who wants to get up to speed on coding to become a test automation engineer, don't just start learning to code; start by learning about source control, a methodology for tracking and managing changes to your code. 

In my recent past, testers at one particular organisation I worked with were busy creating test automation and even tools to manage test data and application state. All the application code was in source control but none of the code written by the testers was in source control. It was zipped and emailed, copied to shared file servers, sent by instant message to name a few sharing mechanisms. Versions diverged wildly, valuable code was lost or overwritten leading to delayed testing, panic rewrites of tools, all round disarray!

Without source control, software developments teams will essentially be in a state of chaos, terrified of code change. I often meet testers without access to their teams source control repository. If this describe you as a tester, you won't be truly closely collaborating with your team.

To bridge that gap, here's what you need to know about source control -- and how to get started. This article will cover:

  • Key disadvantages to you as a tester when you cannot access or use source control repositories and tools.
  • How a grounding in source control will help you to acquire the skills you need to grow as an automation engineer.
  • Important learning resources to complement your on the job experience with source control. 

Disadvantages of Being Source Control Unaware

There are a few key disadvantages you will find yourself as a tester if you don't have access to your team's source control repository and you don't appreciate what happens within:

  • Primary source of collaboration - a lot of communication and collaboration happens within source control and it contains a compelling version of your system and your teams history. There are a number of artifacts that teams collaborate around, usually some form of issue tracking software, a shared wiki page but in my experience these are the least active. The truly active oracle for change is the code itself, where the most collaborative work is taking place, during code reviews and merges.
  • Serious risks - if you don't know what your teams source control strategy is, you might be missing out on serious risks. Long lived feature branches might indicate integration problems later down the line. When there is an issue on your kanban board for a while, there might also be feature branch that has been alive just as long and depending on your release cadence further away from your master branch. As a result code merges might be longer and more difficult, even leading to re-implementing sections of code.
  • Quality advocacy - as testers, we want to be strong advocates for quality. Effective use of source control is one of the key leading indicators of quality, not just for code, for configuration as well. Advocating for more effective use of source control can help our teams achieve better quality outcomes especially in safety and speed of deployments. We can advocate for smaller batch sizes for shorter lived branches, application configuration in source control, even encouraging storing database schema changes too.
  • Early testing - often testers wait around for a build. Waiting for someone to complete a merge and deploy onto a test environment. Imagine being able to test the branch that has been created for your new feature straight away? If you were able to run an application locally or build to an environment from a branch you could test earlier, creating a tighter feedback loop with your team and wider group of stakeholders. 

Source Control as Skills Gateway

Learning source control concepts and skills are a gateway to the other technical skills that are valuable for test automation engineers to learn:

  • Bash - although user interfaces exist for popular source control technologies you will likely be exposed to interactions using the command line, which is where a lot of developers and system administrators on your team spend their time. This then opens the door to bash for UNIX users, with its many commands for teasing out information. Check out Julia Evans Wizard Zines for more.
  • Establishing coding habits - if you have access to your application code, you can see the patterns for the code within and learn from them in your own code. Positive behaviours such as striving for single responsibility, appropriate levels of reusability and sensible abstraction between implementation and test are worth looking out for and adding to your coding toolkit. The opposite is also true, where you can learn from the bad examples within your application code!
  • Pipeline integration - without source control, any test automation that you create will be difficult to integrate with your deployment pipeline tooling, where it can add massive post deployment value. Tools such as Jenkins have built in source control integration enabling you to get your test automation code running where it matters, with the experience of adding to your team's pipeline.

Sources of Inspiration

My journey into the world of source control began with 'The Git Parable' by Tom Preston-Werner. I learn a great deal from story telling as a medium and parable is no different, teaching concepts with reference to characters and situations that resonate with me. If I was to pick a starting point, try this:

However, each has their own learning style (or more likely mix of styles) so here's some next steps, depending on how you like to consume learning material:


Learning source control is an important step in a test automation engineers journey:

  • Without source control awareness, you will experience limits to your collaboration with your team, identifying risks, testing early and advocating for quality.
  • Source control is a gateway to many other skills that will make you an effective test automation engineer. Unlocking the potential of the command line, establishing coding habits by recognising patterns and integrate your tests with your deployment pipeline.

If you want to add value, collaborate with your team and add momentum to your learning, start with source control. Your team and your career will thank you for it.

This post was originally published by the great people at TechBeacon here:

Sunday, 2 December 2018

Modelling a unit of your system

Sunshine, zebras and great conversations

Over the last few days I've been in South Africa for Lets Test, held on a fantastic country retreat near Johannesburg. I facilitated a session called a 'Testers Guide to the Illusions of Unit Testing.' I have a confession to make. We had 2 hours to complete the workshop and, in the spirit of having too much content being way better than too little, we didn't get to delve deeply into this question. Hence this blogpost. 

We had great conversations about how unit testing is an interface between testers and developers, a gateway for deep collaboration. This is predicated on an understanding of unit testing, including what they can and can't achieve and what relation they bear to other types of testing. One of the questions we wished to tackle was:
What is a unit of our system?
How many times have you started to test a system and asked "Hey, what are the unit tests like for this unique piece of software history?" The answer in my experience has often been, "um, yeah, about that we don't have any, its too complex/there is no time/its going to deprecated one day." Or alternatively you are involved in a session about the architecture of a brand new system using the latest technologies, using microservices, lambdas or whatever. In either case, wouldn't it be useful to be able to facilitate a discussion about what is a unit of that system and what factors influence it? You might find yourself with a simpler, more observable, controllable and understandable system. Whats not to like?

Reinventing the wheel

The model itself is another wheel. Other shapes are available, although not when I model something apparently. I added a bunch of segments to the wheel that I think impact the size and shape of a unit in a systems context. The key thing here is context, I know that there are definitions of what a unit test is, contested definitions most of the time. What there isn't a definition for what is a unit of YOUR system, the one that YOU work on. Maybe you can use the above to help your team work it out.

There are key areas here, without delving into each one individually:
  • How the code is stored
  • Who contributes to it
  • What architecture and patterns are present
  • How tightly coupled the system is

The segments are also on a scale of size too. As in what factors contribute to a unit being large or small. For example:

  • Large - Single Database for Multiple Applications - this system may have a gigantic database bottleneck, perhaps even changes that one system makes can impact another. That's a weighty unit.
  • Medium - Broker/Queue Based - maybe messages are routed using built in routing configuration capabilities of RabbitMQ? A unit of this system involves invoking (or mocking) multiple systems so could be seen to have largeness too.
  • Small - Microservice(s) - a service that does one thing well - this could be a unit in itself. At the very least, it indicates that units of your system might tend towards smallness.

Explaining with questions

The notes below include questions and examples of each of the sections. They may be useful as further prompts:

### Architectural Patterns
* What type of system architecture is employed?
* How many layers or tiers does it have?
* How many roles do components within have?
* Examples:
 * Three tier
 * Microservices
 * Broker/queue based
 * Model-view-controller 

### Coding Practices
* How do contributors collaborate over code?
* What design patterns are employed with the code?
* To what extent does testing drive the coding process?
* Examples:
 * Driving Development with Tests
 * Pairing
 * Code reviews
 * SOLID principles
 * Inheritance
 * Abstraction 

### Concurrent Teams 
* How many teams contribute concurrently to the repository?
* Are they internal or external teams?
* Which teams are core maintainers?
* Examples:
 * Internal development teams
 * Outsourced development teams
 * Contributors to key libraries 

### Source Control Strategy
* What strategy does your team employ to manage code?
* What size changes are often checked in?
* How long until changes are integrated with trunk?
* Examples:
 * GitHub Flow
 * GitFlow
 * Trunk based development

### Source Control Repo
* How large is the repository that you have?
* How many linked repositories does it have?
* How does it manage its dependencies?
* Examples:
 * Monolith
 * Monorepo
 * Microlith 

### Size of Objects/Data 
* What are the key data items that the code manages?
* What size are the important items?
* What depends on those important items?
* Examples:
 * Core classes instantiated for every interaction
 * Persistence of customer data
 * Transaction and audit histories 

### Risk to Whole
* What dependencies exist within your code?
* Are they any common objects or structures?
* Are there any areas teams fear to touch?
* Examples:
 * Large common classes with multiple roles
 * Old versions of dependencies
 * Hard coding/configuration in the code 
### Time Periods Used
* What is the lifespan of objects/data created by your code?
* Are there wide differences in the lifespan of different types of objects used?
* Examples:
 * Long lived daemons
 * Scheduled tasks
 * Asynchronous HTTP requests
 * Cache size and expiry rules

Over to you

Essentially, the wheel and guidance is a prompt to help answer these questions about your own system.

  • What factors help to find a unit of your system? (the segments of the wheel, which can be the ones I added, or if you don't like them I have others)
  • What practices & patterns influence that unit? (your own ways of working and crafting principles)
  • How practices and patterns govern size of a unit? (how the way you build stuff affects your ability to test small units of that stuff)


As with all models, this has some holes in it. Not all layers of the system will have the same size unit for example. What is a unit when you test a React application using Jest for example? What unit is creating snapshot files that creates html testing? An interesting questions plus a new and (welcome) challenge to the orthodoxy of automated/unit testing.

Trying to determine what a unit of your system is, will, at the very least lead to asking some searching questions which may provoke a reaction within your team. Overall smallness is the aim for me. After all, if asking these questions serves to help shrink a unit of your system. I believe that testers can be powerful catalysts in this regard.