A few months ago, I had the opportunity to join Craig Larman at a client for an informed-consent workshop on Large-scale Scrum (LeSS). Ever since I took his class in 2015, I was interested in how he starts off a LeSS adoption – or potential LeSS adoption, I should say. He asked me to do a write-up.
We had overall four days at the client. The first day was half Legacy TDD and half Impact Mapping. For day two and three we were off-site from the client with about 30 employees from different departments including finance and controlling, organizational development, and the CEO. The final fourth day we spent back at the client answering questions, and a three hours all-hands introduction to LeSS.Contracting
Craig shared a google document with me, that he also shared with the client. There were a couple of things he made sure up-front, including a description of the company, questions from client to Craig, from Craig to client, and the invitation mail to the workshop participants among the motivation part for LeSS. That was interesting to me since I usually do that verbally or on the phone, whereas a shared document appeared straightforward to me.Half-day Legacy TDD
On the first day, we spent the morning on some legacy code. We had about 10 developers joining us. Craig gave a short introduction to TDD and the difference to Legacy TDD. Then we worked in a mob with a rotation of a few minutes. In those four hours, we managed to write two tests for one of their legacy PHP classes. The first test appeared a bit daunting, but Craig also explained lots of things around dependencies, how to deal with them, differences between stubbing and mocking, etc., etc. It paid off for the second test, as we were able to write that faster since we already had some scaffolding from the first test in place.Half-day Impact Mapping
In the afternoon, we spent another four hours with the product management group. Most of them were called Product Owner, but also the CEO and one of their Scrum Masters joined us. Craig explained the general approach and had the group identify a goal. Then the group worked through the impacted persons towards the impact that they needed to achieve there in order to get closer to the goal. We also mapped some of the deliverables that were already in their backlogs. At the end of the day, the group took a longer time to agree on a goal, so that we didn’t have time to actually estimate the impacts, and the deliverables, so that Craig explained the steps that were missing.
What strikes me about the first day was that Craig spent a day at gemba in a value-adding way. He worked with the programmers on their production code in the morning, and with the product group in the afternoon. In both cases, he was able to add value to different groups while getting an overview of how work is done at the client.Workshop Day 1
In general I had a pretty good impression of the workshop. Craig led through the Thinking Tools behind LeSS. He started off with Occupational Psychology, and how fear hinders any adoption. We worked in great length through the different kinds of waste, queueing theory, and created Causal Loop Diagrams for a couple of dynamics that were the main motivation behind the elements in LeSS. Craig avoided to mention anything LeSS specific on day one. Instead he made the point for one backlog per product quite clear, in that the dynamic with more backlogs, i.e. one backlog per team, leads to sub-optimal identification with the customer. Compared to the course I took in February 2015, I found that the argumentation followed a clear line. Thus I could see the improvements to the material in action since then.Workshop Day 2
On the second day, we dived deeper into LeSS with a short introduction on the framework as well as some adoption notes. We spent the second half of the second day with Craig’s deep dive into questions that had come up. Anyone who has attended Craig’s course probably knows what I’m talking about. Craig spent lots of time to get deep into the answer so that participants grasped the context of the answers and thoughts behind LeSS.Day 3 Q&A and Informed Consent
On day 3 we spent the morning with other potential coaches and some volunteers back in the client’s office. We worked through some open questions, and then Craig urged the group to come up with next tiny steps to do before starting bigger changes in a month or two. He also ran an anonymous non-committing poll on whether the group wanted to go with LeSS. There were two objectors, eight in favor (iirc), and the majority of the group would go along, i.e. not resisting, but also not actively pushing forwards. Personally I think they identified way more next steps as I would have called suitable for the one or two months timeframe.
After that I had to leave for my train ride home, but Craig also did a whole company introduction to LeSS. I don’t know what happened there, though.
The overall goal of the four days was to make an informed decision at the client to either go for LeSS or something else. Craig made sure that the client made the decision where to go, and made sure that people in the workshop could understand potential side-effects. Together with the Causal Loop Diagrams they should be able now to evaluate their future struggles.
It’s been a while since I wrote code these days. Back in late April however I found myself in a Coding Dojo at the Düsseldorf Softwerkskammer meet-up working on the Mars Rover Kata. I have a story to share from that meeting. However, since I tried to reproduce the code we ended up with that night, and I decided to give JUnit5 (and Java8) a go for that, I ended up with a struggle.
Back in the days with JUnit4 I used the ParameterizedRunner quite often to use data-driven tests. I never remembered the signature of the @Parameters function, though. The Mars Rover Kata also includes some behavior that I wanted to run through a data-driven test, but how do you do that in JUnit5? I couldn’t find good answers for that on the Internet, so I decided to put my solution up here – probably for lots of critique.
Please note that I used JUnit 5.0.0-SNAPSHOT which is a later version than the alpha, but probably not the final one.
JUnit5 offers besides Java 8 capabilities some interesting new things. JUnit5 comes now with Extension capabilities where you may influence the test’s lifecycle and also ways to resolve parameters to your tests, and your test class constructors. And then there are TestFactories for DynamicTests. Woha, quite a lot new stuff.
First I tried stuff with parameter resolvers. But then I would have needed to keep track of the parameters, and I had to call the parameter resolver more than once. So, combining it with an extension might work? No, I couldn’t make that work. So, dynamic tests are the way to go.
So, here is an example for what I ended up with. We have a Direction class with a method called turnLeft(). The idea is if the Rover is headed NORTH, and turns left (by 90 degrees) then it will be facing WEST.
- I kept a collection of test data in a field in line 17. This is somewhat similar to the old way you annotated a function with @Parameters in JUnit4, even though you can now get rid of the Object, and use a private test data class per test class. That at least seems to be the solution that I preferred.
- For the @TestFactory you have several possibilities. I decided to use the Stream return type here in line 28. As I haven’t programmed too much in Java 8, I am not sure whether my usage is appropriate here. The conversion of the testData from the Collection is quite straight-forward, I found.
- For each operation I wrapped the assertion in line 36 to avoid making the call to dynamicTest more convoluted than necessary. I also decided to generate a descriptive string for each test with the method in line 32. I think you can come up with better ways to generate the test descriptions. Wrapping the assertion on seemed unavoidable though. I especially didn’t like the usage of the lambda-expression together with the aggregate expression seems to make the line with dynamicTest (line 29) less readable than I would like to. I think there is more improvement possible.
- Note that you can have several @TestFactory methods on your test class. So when writing a test for turning right, you can provide another TestFactory and reuse the test data for that. I’ll leave that as an exercise for the inspired reader of my blog.
So, this is what I ended up with. I think there is still room for improvement, especially when you compare the result with stuff you might write in tools like Spock.
P.S.: I ran this through Marc Philipp – one of the JUnit5 originators – in an earlier version, and he told me that they will be working on a more elegant solution for data-driven tests, probably for one of the next releases of JUnit5.