Learning about test automation with Lego
“Hold on, did you say that I can learn about test automation by playing with Lego? Shut up and take my money!” Yes, I am indeed saying that you can. It will cost you a couple hundred Euro’s, because Lego isn’t cheap, especially the Mindstorm EV3 Lego. It turns out that Lego robots eat at a lot of AA batteries, so buy a couple of packs of these as well. On the software side you need to have a computer with a Java development environment and an IDE of your choice (the free edition of IntelliJ IDEA will do).
“Okay, hold on a second. Why do you need Java? I thought Lego had its own programming language?”. Yes, that’s true. Orginally, Lego provides you with their own visual programming language. I mean, the audience for the EV3 is actually kids, but it will be our little secret. Because Lego is awesome, even for adults. Some hero made a Java library that can communicate with the EV3 hardware, LeJos, so you can do more awesome stuff with it. Another hero dedicated a whole website to his Mindstorm projects, including instructions on how to build them.
Starting the project
So, on a sunny innovation day in August at Xebia, Erik Zeedijk and I started our own Lego project. The goal was to make something cool and relevant for Testworks Conf. We decided to go for The Ultimate Machine, also known as The Most Useless Machine. It took us about three hours to assemble the Lego. If you’re not familiar with the Useless Machine, check this video below.
Somehow, we had to combine Lego with test automation. We decided to use the Cucumber framework and write acceptance tests in it. That way, we could also use that to figure out what options we wanted to give the machine (sort of a requirements phase…what did I just say!?). The Ultimate Machine can do more than just turn off the switch, as you could tell if you watched the above video. It can detect when a hand is hovering above the switch and that can trigger all kinds of actions: driving away to trick the human, hiding the switch to trick the human, etc. With Acceptance Test Driven Development, we could write out all these actions in tests and use those tests to drive our coding. In that sense, we were also using Test Driven Development. In the picture below is an example of a Cucumber feature file that we used.
The idea sounded really simple, but executing it was a bit harder. We made a conceptual mistake at first. To run our tests, we first coded them in a way that still required a human (someone who turned the switch on). Also, the tests were testing the Lego hardware too (the sensors) and not our own code. The Lego hardware has quite some bugs in it, we noticed. Some of the sensors aren’t really accurate in the values they return. After some frustration and thinking we found a way to solve our problem. In the end, the solution is pretty elegant and in retrospect I face-palm because of my own inability to see it earlier.
We had to mock the Lego hardware (the infrared sensor and the motors), because it was unreliable and we wanted to test our own code. We also had to mock the human out of the tests. This meant that we didn’t even need the Lego robot anymore to run our tests. We decided to use Mockito for our mock setup. In the end, the setup looked like this.
The LeJos Java library uses a couple of concepts that are important to grasp. An arbitrator decides which behavior should run. All the behaviors are put in a
behaviorList Inside each behavior is a boolean
wantControl that becomes ‘true’ when certain conditions arise. See the picture below for an example ‘wantControl’ in the DriveBehavior class.
Then the behavior starts to run and when it is finished it returns ‘idle = true’. The arbitrator then picks a new behavior to run. Because some behaviors had the same conditions for ‘wantControl’ we had to think of a way to prevent the same behavior from triggering all the time. In each behavior we put a boolean
chanceOfBehaviorHappening and we assigned a chance to it. After a bit of tweaking we had the robot running the way we liked it.
The tests were reliable after this refactoring and super fast. The test code was neatly separated from the code that implemented the robot’s behaviour. In addition, you could start the real Lego robot and play with it. This is a picture of our finished robot.
We didn’t implement all the behaviors we identified on purpose, because our goal was to get attendants of TestWorks Conf to code for our robot. This little project has taught both Erik and me more about writing good Cucumber feature files, TDD and programming. We are both not really Java experts, so this project was a great way of learning for both of us. I certainly improved my understanding of Object Oriented programming. But even if you are a seasoned programmer, this project could be nice to increase your understanding of Cucumber, TDD or ATDD. So, convince your boss to shell out a couple hundred to buy this robot for you and start learning and have fun.
FYI: I will take the robot with me to the Agile Testing Days, so if you are reading this and going there too, look me up and have a go at coding.