Improving Collaboration Between Developers and Testers

One of the biggest divides you need to cross, even on agile teams, is the chasm between testers and developers. By the nature of their different roles there will always be tension with developers focusing on creation, change, and construction, and testers focusing on breaking, destructive, and exposing questionable system behaviours. It’s essential that both organisations and, in particular, individuals realise what they can do to ensure this tension doesn’t dissolve into an exclusively confrontational relationship.

catdogfight

Photo taken from Sephiroty’s Flickr stream under the Creative Commons licence

Recently, a new QA person highlighted this very issue for me. I’d finished some functionality with my pair and the QA had been testing it after we declared it ready to test. They came along to my desk and said, “I’ve found some defects with your code.” Internally I winced as I noticed myself wanting to say, “There’s nothing wrong with my code.” It got me thinking about why.

Evaluating people puts them on the defensive
Just as giving effective feedback should focus on behaviour, poor feedback makes a person feel criticised. When the QA said that there are some “defects”, it implied a broken state that you had to fix it. Made worse is the way that they said it made it feel like they were blaming you, and it’s very hard not to feel defensive in a situation like this. A very natural outcome is to pretty much deny the “evaluation” which I’m sure anyone in our industry would have witnessed at least once.

Avoid terms like “defect”, “broken”, “bugs”
One of the biggest differences working with agile testers versus testers who come from traditional backgrounds is the terms that they use. Traditional testers constantly use the words above. Agile testers focus on discussing the behaviour of the system and what expected behaviour they would see. They only use the words above once they have agreement on both of the both the current and expected behaviours. I definitely recommend you do not start a conversation with the words above as they all carry some connotation of “evaluation” and I’m yet to meet someone who truly feels comfortable being “evaluated”

Focus on Effective Feedback
Effective feedback follows a neat and simple pattern:

  1. What behaviour did you see?
  2. What impact did it have?
  3. What do we want to change?

Testers should use a similar series of questions (in order):

  1. What behaviour did you see?
  2. What behaviours did you expect to see?
  3. What are the consequences of the current system behaviour?
  4. Is that desired or undesired?
  5. Do we need to change it?

Apply the guideline above and watch the collaboration improve!

Repeatability distracts from the real goal

Most organisations emphasise repeating the “process”, serving to distract from the real goal – repeating “success”. You need a certain amount of flexibility and adaptability in your process because you never work in the same environment twice.

This does not mean you do not use things that have worked well for you in the past. It means you should be prepared to change them if you can do it better.

Maximising learning in development: Do Things Multiple Times

Cockburn talks about waterfall development being a poor strategy for learning so what do agile methods give us that allows us to learn better?

One thing I constantly remind myself is that we tend to be write pretty poor code the first time we do it. Unfortunately most people also write a lot of first time code, check it in and move on. Refactoring is one strategy that lets you learn about how to change the code better and is often one that most people reach for.

One practice that I’ve been doing more and more frequently is Do things multiple times. Sounds horrific right? Sounds like a huge waste of time? I think it can be if you don’t learn anything from it. Therefore in order to maximise learning, I think you need to also master a number of supporting practices like Use Version Control, Check in Frequently, Small Commits, and Automated Tests.

Here’s an example of this practice in action:

I’d seen some spike code that had somehow made it’s way into the codebase. It had minimal test coverage, had many more lines of code than I was comfortable with and involved many different classes all slightly dependent on each other in some way. I wanted to refactor it but didn’t really know what the best way of doing it was. I retrofitted some tests around it, running code coverage to get a good understanding about what areas I was now more comfortable changing. I ran the build, got the green light and checked in.

I applied some small refactorings, ran the tests and watched everything spectacularly break. I looked back at what I did and started to understand some of the relationships better. I rolled everything back, this time trying something slightly different, before running the tests again. Things broke in a slightly different way and I spent a little bit of time understanding what happened this time. I rolled things back again and then tried a different approach. I want to emphasise that the timeframe for this is about fifteen or twenty minutes.

Compare it to other approaches I see quite frequently, where someone sets out to do something, gets into a broken situation, finds something else to fix and ends up working on multiple things at once. They keep patching stuff to get the tests to pass again, and once they do, check in and move on.

You should only Do things multiple times if you can Check in Frequently, execute Small Commits (therefore you lose very little when you rollback) and have Automated Tests so you know if you broke anything.

Repeating something is only waste if you don’t learn anything from it.

Active Passive Load Balancer Configuration for HAProxy

It took me a while to understand the help for the configuration file for HAProxy, another software load balancer that runs on a number of *nix-based systems. Here’s the resulting file that we used to successfully test an active-passive machine configuration that someone will hopefully find useful one day.

global
    log     127.0.0.1 alert
    log     127.0.0.1 alert debug
    maxconn 4096

defaults
    log        global
    mode       http
    option     httplog
    option     dontlognull
    option     redispatch
    retries    3
    maxconn    2000
    contimeout 5000
    clitimeout 50000
    srvtimeout 50000

####################################
#
#           loadbalancer
#         10.0.16.222:8555
#           /          \
#   webServerA         webServerB
# 10.0.5.91:8181     10.0.5.92:8181
#    (active)           (passive)
#
####################################

listen webfarm 10.0.16.222:8555
    mode    http
    stats   enable
    balance roundrobin
    option  httpclose
    option  forwardfor
    option  httplog
    option  httpchk    GET /someService/isAlive
    server  webServerA 10.0.5.91:8181 check inter 5000 downinter 500    # active node
    server  webServerB 10.0.5.92:8181 check inter 5000 backup           # passive node

Active Passive Load Balancer Configuration for Nginx

Here’s the configuration file that we ended up with testing an active passive configuration for our application using the software load balancer Nginx that I previously posted about.

worker_processes  1;
error_log  logs/error.log;
events {
    worker_connections  1024;
}

####################################
#
#          loadbalancer
#         localhost:7777
#           /          \
#   webServerA         webServerB
# localhost:8080      localhost:8181
#    (active)           (passive)
#
####################################

http {
    include               mime.types;
    default_type          application/octet-stream;
    proxy_connect_timeout 2s;
    proxy_read_timeout    2s;

    sendfile              on;
    keepalive_timeout     65;

    upstream backend {
        server 127.0.0.1:8080     fail_timeout=1s max_fails=1;    # active node
        server 127.0.0.1:8181     backup;                         # passive node
    }

    server {
        listen                   7777;
        server_name  localhost;

        location / {
            proxy_pass http://backend;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

Windows Software Load Balancer

nginx-logoI needed to test our application behind a load balancer using a windows machine. Scouring the web didn’t turn up anything particularly useful… all heavy weight, commercial products. Then I stumbled across http://nginx.org/.

It played its part perfectly. Ignore the ugly home page and go straight to their wiki instead.

A guide for receiving feedback

I recently gave some advice on how to give feedback effectively and was asked to give some advice about receiving feedback. My guidelines for receiving feedback are pretty much based on understanding how to give effective feedback. Ola recently also shared his experiences with this.

Before I understanding how to receive feedback, it’s useful to recap some guidelines on how to give feedback:

  • Feedback should be specific. Talk about specific observations and impact of the behaviours exhibited during those observations.
  • Believe that someone was doing what they thought was correct at the time. (Akin to the Retrospective Prime Directive)
  • Feedback should be timely. Give it early and often as you see fit.
  • Feedback should be about both strengthening confidence and improving effectiveness. It shouldn’t be about making someone feel bad about themselves.
  • The focus of feedback should be about behaviours, not perceived values or attitudes.

When you receive feedback, be prepared not to receive feedback in an ideal manner. For many different reasons, most people find it difficult to give effective feedback, often requiring plenty of practice to get almost incrementally better at it.

Gift

Photo taken the Powerhouse Museum’s Flickr Stream under the Creative Commons licence

Listen candidly
When I receive feedback, I try to listen without reacting immediately to the feedback. Some common (ineffective) feedback people give is something like, “Your code is awful”. When put that way, who isn’t going to get defensive? Even something like “You’re really great” makes it hard to understand what behaviours you should continue repeating, and what behaviours you might consider changing. It’s particularly challenging listening to other feedback if you’ve already been put on the defensive, therefore…

Clarify detail and ask for specifics
When you feel offended or shocked with the feedback, ask for what observations people made to reach that conclusion. I like to ask for what observations they made and what impact it had, as well as how they felt about it. For some people, it’s useful to help them understand that you currently feel defensive. I might say something like, “I feel like I’ve just been judged and feeling defensive. I’d like to understand what behaviours you saw had a negative impact so that I can better understand your perspective.”

Share your context with them
People often jump to the wrong conclusion because they may not have the complete picture. It’s often useful to share other motivating forces about the same observed behaviours. For example, “I joined the conversation uninvited because I feared you would never ask me for my input and I felt I had important things to contribute.”

Acknowledge and thank them for their feedback
When people give feedback, they are giving up some of their time. Some people may have overcome certain fears about giving feedback. So when you’re receiving them, ensure that you acknowledge what they are saying and thank them for their feedback. Even if you disagree with their conclusion acknowledge their contribution if you also observed the same behaviour.

Ask for feedback early and often
Giving effective feedback takes time and isn’t often at the front of people’s minds. We know that it’s easier to respond to feedback early when you have an opportunity to change something. As the person receiving feedback, it often helps to invite people to give you feedback as this alleviates the fear most people have when giving feedback, “How are you going to react?” Giving people some notice about collecting feedback also helps.

Move people away from judgements to positive action items
For some people, it will be difficult to move them away from their “evaluation” and brining them back to observed behaviours. Also, some people don’t take remember specific behaviours or impact and like to talk about their “gut feeling”. While this isn’t particularly effective, as a person receiving feedback you can still benefit by asking them, “What should I do differently?” or “What could I do to make more of the situation, or make the situation better?”

What helps you?
I’m sure there are plenty of other tips on how to receive feedback. What do you tend to focus on when receiving feedback?

Why ISO9001 standards fail

Systems and standards with good intentions are naught without proper execution. Unfortunately this is where most people get let down. People adopting agile fall into the same traps, but at least the Agile Manifesto guides people in terms of values.

Here’s how I’ve seen ISO9001 being communicated at various clients:

  • ISO9001 is a quality management system
  • A core part of ISO9001 is about control and documenting processes
  • ISO9001 is about continuous improvement

Seems harmless right? Unfortunately the way that people interpret this is as the following. ISO9001 is a quality management system. Quality management system = control and documenting processes. Control and documenting processes = continuous improvement.

Unfortunately most people never escape out of the control and documentation requirements, and the fear of failing and audit that leads to a micro-optimisation. This is why the manifesto talks about “uncovering better ways of developing software by doing it and helping others do it” and prioritising “individuals and interactions over processes and tools“.

Apparently I dislike OO

Wow. I am stunned. Apparently I don’t like Object Oriented programming because I think inheritance is a poor man’s method for reuse. Hmm…

Lack of retrospectives a smell?

On our current project, we haven’t run many retrospectives. Gasp! Anyone who knows me might be shocked to hear that.

I’ve pondered whether or not that this has been a bad thing for our project. I’m a huge advocate for using retrospectives to help encourage people to create change on their projects. I’m a huge advocate for using retrospectives to bring the team together and understand what’s going on. Fortunately I’m lucky that our team has some very strong people with probably 40% of them having true skin-in-the-game experience working on agile teams that things just get done and more importantly, things continuously improve.

I definitely believe that without all the experienced agile team members, we wouldn’t have overcome all the different and sometimes bizarre situations (ask me if you see me!) thrown our way. Do I think retrospectives still offer us some value? Yes, but probably not for the reasons that most people use it for.

It’s amazing what a bunch of energised, passionate and people with the “solve the right problem once” attitude can achieve. I’d only wish that more teams were made up of people like this more often!

Next Page »