September 22, 2017
Evil FizzBuzz (or "So you think you're a team?")Among the advanced topics we cover on the third day of the Codemanship TDD course, Continuous Integration presents some of the biggest challenges for dev teams.
Participants are subjected to an exercise called Evil FizzBuzz, which you might like to try on your team (or at your coding event).
Based on the drinking game, FizzBuzz is a very simple algorithm.
1. Generate a sequence of integers from 1 to 100.
2. Any integers that are divisible by 3, replace with "Fizz".
3. Any that are divisible by 5, replace with "Buzz".
4. Any that are divisible by 3 and 5, "FizzBuzz".
5. And, for a bit of extra spice, any that are prime numbers, replace with - or concatenate if already "Fizz" or "Buzz" - "Wizz".
6. Output as a comma-delimited string.
So the first 15 in the sequence would go:
1, Wizz, FizzWizz, 4, BuzzWizz, Fizz, Wizz, 8, Fizz, Buzz, Wizz, Fizz, Wizz, 14, FizzBuzz
This is pretty straightforward for a programmer to code a solution to, and makes a spiffy exercise for learning about triangulation in TDD.
Now to make it evil...
* Split the group up into 6 pairs (or threes, or ones, depending on how many people you've got).
* Assign each part of FizzBuzz above (1-6) to a pair. They can only work on code for that part of the whole.
* Task them to work together - but only coding/TDD-ing their individual parts - to deliver a complete solution that produce the desired output.
Give them about an hour. And stand back and enjoy the train wreck.
To achieve this, they need distributed version control. So someone in the group needs to create, say, a GitHub repository that they can all contribute to. Then someone needs to put the skeleton of a source code project in that repository for pairs to work in. Then someone needs to set up Continuous Integration for that source code project so that merges can be built and tested.
All of this typically takes up more than half the time allotted. And until they have a green build to merge into, everybody's blocked from pushing. The yak shaving's what trips up half the groups I've seen attempt Evil FizzBuzz. DevOps is not commonly our strong suit.
And, of course, they have to agree on stuff. They have to agree on what language they're going to use. They have to agree on a basic design for how all the parts will fit together. They have to agree on how the process of collaboration's going to work if they're not going to end up tripping over each other's feet.
This is where the other half usually come unstuck. Most developers and dev orgs just aren't used to this level of collaboration. It's intense. Really intense. What usually happens is they either spend 50 minutes out of their hour arguing and getting nowhere, or they just go off into their separate corners and do their own thing. Both lead to failure.
And then there's the whole lesson behind the exercise: if the group isn't disciplined about CI, they will fail to deliver Evil FizzBuzz. Guaranteed.
What I mean by that is that the protocols of CI need to be keenly observed to prevent pairs merging conflicting changes on top of each other. And the feedback CI gives us about where the code's going must not be ignored. Every pair should be keeping one eye on the build. When they see a new build succeed, it's time to get the latest changes and see how it fits in with what you're doing.
Agreeing on things. DevOps. Constant communication. Situational awareness. Coordinating. All things dev teams tend to suck at.
And that's why I love this exercise. Especially on the rare occasions that you see a group ace it, like my training client this week. It speaks volumes about them as a team, and it's a joy to watch it unfold as each build goes green and you see the solution taking shape in front of your eyes.
The purpose of Evil FizzBuzz is to (hopefully) open dev teams' eyes to CI as a means of communication in collaborative design, and in particular to just how intense that collaboration often needs to be, and how disciplined about CI they need to be for it to work.
I'll bet you a shiny penny your team can't do it. Most can't.
Now prove me wrong.
August 29, 2017
Putting .NET Unit Tests In The Same Project As Source Code (?)Something's been bugging for me for quite some time. About 15 years, in fact.
The convention in .NET development has been to have separate source and test projects.
While this provides a clean separation when it comes to builds, that comes at a price. Any class or method I want to reference in a test has to be public.
So either we make a bunch of stuff public so we can test it, or we test through a teeny tiny public "keyhole", which leads to the code being tested often being many layers removed from its unit tests. This is not good for debuggability.
In Java, we don't really do this. There would typlically be one Eclipse or IntelliJ project with a folder for the source code and a folder for the test code. Classes that are only internally visible inside that project can be unit tested easily.
And I've been wondering why we don't also do this in .NET? What if I were to move the tests into a subfolder of the source project?
Then I could make the class under test internal, minimising visibility is that class doesn't need to be exposed in an API.
Ah, but - I hear you ask - what happens when we build the project? Do we really want to include all the public test classes and have a reference to the unit testing framework?
No problem. We can edit the .csproj file to only include the tests and associated DLL references in a debug build.
A next step might be to create a Visual Studio project template that's already set up with the Test subfolder and DLL reference for unit testing, with the build configurations tweaked appropriately.
Easy as peas. Now why weren't we doing this all along?
So this has turned out to be a little more controversial than I thought.
Firstly, thanks to @vgaltes for pointing me to this resource that says you can actually mark "friendly" assemblies that can see another assemblies internal features. I didn't know that.
That would be a clean way of achieving the goal of being able to unit test classes and methods without making them public.
Another school of thought is that you shouldn't have tests for internal details, and should only test through public APIs. This theoretically makes internal refactoring easier. Been there, done that, and got the "I Love My Debugger" t-shirt.
In practice, I've found that testing through a public "keyhole" can lead to unit tests that are often far-removed from the code they're testing. And to ease refactoring, I'd prefer better and more focused unit tests that are loosely coupled to the interfaces of the objects they're testing.
That's not to say, of course, that you shouldn't have API tests. I highly recommend them; partly because they're useful for figuring out what your API design needs (a client code perspective), partly because they can serve as a "user manual" for client developers, and partly for testing backwards compatibility by running old tests against new implementations.
Now it may be, of course, that your API is extensive and that many of the classes, interfaces and methods in your project are public anyway.
But the designs I tend to end up with often favour public interfaces implemented by non-public classes. The tests need to get a hold of the implementations.
Of course, you can skin this cat in many different ways, and a lot will depend on your build & config needs, your testing approach and your architecture.
The fact remains, though, that we put source and tests in the same projects in other languages without giving it a second thought. On larger solutions, I often find it cumbersome to have 2x projects for everything. Take a look at this Refactoring Golf solution, for example. Tied myself in knots with that one.
No doubt this debate will continue.
August 11, 2017
Update: Code Craft "Driving Test" FxCop Rules
I've been continuing work on a tool to automatically analyse .NET code submitted for the Code Craft "Driving Test".
Despite tying myself in knots for the first week trying to build a whole code analysis and reporting framework - when will I ever learn?! - I'm making good progress with Plan B this week.
Plan B is to go with the Visual Studio code analysis infrastructure (basically, FxCop). It's been more than a decade since I wrote FxCop rules, and it's been an uphill battle wrapping my head around it again (along with all the changes they've made since 2006).
But I now have 8 code quality rules that are kind of sort of working. Some work well. Some need more thought.
1. Methods can't be longer than 10 LOC
2. Methods can't have > 2 branches
3. Identifiers must be <= 20 characters. (Plan is to exempt test fixture/method names. TO-DO.)
4. Classes can't have > 8 methods (so max class size is 80 LOC)
5. Methods can't use more than one feature of another class. (My very basic interpretation of "Feature Envy". Again, TO-DO to improve that. Again, test code may be exempt.)
6. Boolean parameters are not allowed
7. Methods can't have > 3 parameters
8. Methods can't instantiate project types, unless they are factory or builder methods that return an abstract type. (The beginning of my Dependency Inversion "pincer movement". 2 more rules to come preventing invocation of static project methods, and methods that aren't virtual or abstract. Again, factories and builders will be exempt, as well as test code.)
What's been really fun about the last couple of weeks has been eating my own dog food. As each new rule emerges, I've been applying it frequently to my own code. I'm a great believer in the power of Continuous Inspection, and this has been a timely reminder of just how powerful it can be.
After passing every test, and performing every refactoring, I run a code analysis that will eventually systematically check all my code for 15 or so issues. I fix any problems it raises there and then. I don't commit or push code that fails code analysis.
In Continuous Inspection, this is the equivalent of all my tests being green. Of course, as with functional tests, the resulting code quality may only be as good as the code quality tests. And I'm refining them with more and more examples, and applying them to real code to see what designs they encourage. So far, not so shabby.
And for those inevitable occasions when blindly obeying the design rules would make our code worse, the tool will have a mechanism for opting out of a rule. (Probably a custom attribute that you can apply to classes and fields and methods etc, specifying which rule you're breaking and - most importantly - documenting why. Again, a TO-DO.) In the Driving Test, I'm thinking candidates will get 3 such "hall passes".
If you want to see the work so far, and try it out for yourself, the source code's at https://github.com/jasongorman/CodeCraft.FxCop
And I've made a handful more tickets available for the trial Code Craft "Driving Test" for C# developers on Sept 16th. It's free this time, in exchange for your adventerous and forgiving participation in this business experiment :)
August 9, 2017
Clean Code isn't a Programming Luxury. It's a Business NecessityI'm not going to call out the tweeter, to spare their blushes, but today I saw one of those regular tweets denigrating the business value of "clean code".
This is an all-too-common sentiment I see being expressed at all levels in our industry. Clean Code is a luxury. A nice-to-have. It's just prima donna programmers making their code pretty. Etc etc.
Nothing could be further from the truth. Just from direct personal experience, I've seen several major businesses brought to their knees by their inability to adapt and evolve their software.
There was the financial services company who struggled for nearly a year to produce a stable release of the new features their sales people desperately needed.
There was the mobile software giant who was burning $100 million a year just fixing bugs while the competition was racing ahead.
There was the online recruitment behemoth who rewrote their entire platform multiple times from scratch because the cost of changing it became too great. Every. Single. Time.
I see time and time again businesses being held back by delays to software releases. In an information economy - which is what we now find ourselves in (up to our necks) - the ability to change software and systems is a fundamental factor in a business's ability to compete.
Far from being a luxury, Clean Code - code that's easy to change - is a basic necessity. It is to the Information Age what coal was to the Industrial Age.
No FTSE500 CEO these days can hatch a plan to change their business that doesn't involve someone somewhere changing software. And the lack of responsiveness from IT is routinely cited as a major limiting factor on how their business performs.
Code craft is not about making our code pretty. It's about delivering value today without blocking more value tomorrow. It's that simple.
August 1, 2017
Codemanship Code Craft Driving Test - Trial Run
In my last blog post, I talked about the code quality criteria for our planned "driving test" for code crafters.
If you're interested in taking the test, I'm planning a trial run on Saturday Sept 16th. Initially, it will be just for C# programmers.
Entry is free (this time). You'll need a decent Internet connection, Visual Studio (2013 or later, Community is fine), and a GitHub account. Resharper is highly recommended (you can download a trial version from https://www.jetbrains.com/resharper/download/ - but don't do it now, because it will time out before the trial!) You'll be writing tests with NUnit 2.6.x. You can use whichever .NET mocking framework you desire. No other third-party libraries should be required.
The project we'll set you should take 4-8 hours, and you'll have 24 hours to submit your solution and your screencast link after we begin.
If you've been on Codemanship training courses, the quality criteria should make sense to you, and you'll know what we're looking for in your screencast.
If you haven't, then I recommend twisting the boss's arm and sending them a link to http://www.codemanship.com :)
You can register using the form below.
July 31, 2017
Codemanship Code Craft "Driving Test" - Code Quality CriteraMuch pondering today about the code quality standards that should be applied in the Codemanship Code Craft Driving Test we'll be trialling at the end of the summer.
Since it's a test, I think it's fair to apply more rigorous and unyielding standards, provided that these are laid out unambiguously in advanced.
We can divide it up into 7 key areas, with some slightly different criteria for test code to allow for more verbose method names and a bit more code duplication:
1. It Works
* Your solution passes all of the customer tests we'll give you
* Your solution also survives a more exhaustive suite of tests to hunt for any lurking bugs
2. It's Readable
* The Conceptual Correlation between your code and the requirements is > 80%
* Non of your identifiers contain > 20 characters (except for test method names)
* No line of your code contains > 100 characters
3. It's Low in Duplication
* A check using Simian will reveal no more than 15% code duplication (We'll give you the precise Simian options so you can check for yourself)
4. It's Made of Simple Parts
* No method will contain > 10 LOC
* No method will have > 2 branches
* No method will have > 3 parameters
* No method will have Boolean parameters
* No class will have > 6 methods
5. It's Made of Swappable Parts
* Excluding in your tests, all dependencies on other classes in your solution will be swappable by dependency injection. Use of DI frameworks will also be forbidden. (Dependency Inversion)
* No non-test class will invoke any method on an instance of another class in the solution that can't be easily extended or swapped (e.g., in C#, only methods on interfaces or virtual methods can be invoked)
6. The Parts Are Loosely Coupled
* No class will depend on > 3 other classes in your solution
* No method will exhibit Feature Envy (when a method of one class uses more than one method of another) for other classes in your solution (Tell, Don't Ask)
* No class or interface will expose features to another class that it doesn't use (Interface Segregation)
* No class will invoke methods on solution classes which are not direct collaborators (i.e., fields or parameters) (Law of Demeter)
7. Test Code Quality
* No unit test will make more than one assertion (or mock object equivalent)
* There will be exactly one unit test method per requirements rule, the name of the test will clearly describe the rule
* All of the unit tests will pass without any external dependencies
* There will be a maximum of 10% integration test code, packaged separately
* The tests will run in < 10 seconds
* Tests will contain < 25% code duplication
Now, even though there's quite a lot of meat on these bones, these criteria may change, of course. But probably not much.
In the trial, I'll be verifying many of them by hand. This will give ma chance to validate them and iron out any conceptual kinks.
The long-term intention is that most - if not all - of these checks will be automated. Initially, I'm working on doing that in C# for the .NET developer community.
The code quality criteria will form half the score for the driving test. To pass it, you'll also need to demonstrate your practices and habits, and explain why you're doing them, so we can evaluate how much insight you have into code craft and the reasons for it. This will be done by recording a 30-minute screencast at some point during the test that we can assess.
More news soon.
July 26, 2017
Gold Standard Teams do Continuous Inspection
Working with so many dev teams across a diverse range of industries gives me a great insight into the common features of teams that consistently do great work.
I call these the Gold Standard development teams. And they write gold standard code.
Gold standard code, to me, is code that maybe only 1% of teams are writing. It's more reliable and more maintainable than 99% of the code I see.
Importantly, Gold Standard dev teams don't usually take any longer to deliver working software than their Silver and Bronze Standard peers. Often, they deliver sooner. And it's no coincidence. The practices that lead to gold standard code also tend to make earlier and more frequent delivery easier.
One common feature I see in Gold Standard dev teams is that they do continuous inspection of their code to ensure that it's of a high quality.
Some teams review code quality once in a blue moon. Some review code in every iteration. Some review code with every check in.
Gold Standard dev teams review code quality as often as they test their code, every few minutes. This means they pick up code quality "bugs" almost as soon as they're introduced.
Like functional bugs, code quality bugs are much easier to fix the sooner they're caught. Catching issues immediately enables Gold Standard dev teams to produce very high quality code at little to no extra cost. Often, it saves time.
Continuous testing of software requires a high level of test automation. It's not really possible any other way. Continuous code inspection is no different. Rigorously examining the code for a multitude of problems every few minutes is extremely difficult to do by eye alone. Pre-check-in reviews, and even pair programming, are not enough.
Luckily, there's an ever-growing supply of tools we can use to automate our code inspections. Unsurprisingly, demand for the specialist skillset required is growing rapidly, too.
What kind of questions should we ask in our continuous code inspections? To some extent, that will depend on your specific code quality goals. But there are themes that are common to most code:
1. Complexity - How much "stuff" is there in our code? How many lines of code in this function or module? How many branches? How many operators and operands?
Gold Standard dev teams know the price of increasing code entropy, and fight it vigorously. Is this method getting a bit big? Let's split it into a composed method. Is this class doing too much? Let's split it into multiple classes that each have one distinct job.
2. Duplication - When we duplicate code - and concepts - we end up having to maintain the same logic in multiple places, multiplying the cost of making changes to it.
Gold Standard dev teams monitor the code closely for similarities. Are these two blocks of code kind of the same? Let's turn it into one parameterised method. Are these two classes sort of doing the same thing? Maybe extract the common elements into their own class and have both of them reuse that.
3. Dependencies - If we change a line of code in one place, how much of the rest of the code will break? Unmanaged dependencies - couplings - in our code can amplify the "ripple effect" and multiply the cost of even the smallest changes.
Gold Standard teams are continually aware of, and constantly managing, the dependencies in their code. When a class depends too much on other classes, they reshape the code and redistribute the responsibilities to localise the impact of change.
They also make sure that as many of their dependencies as possible are swappable: that is, one function or class or component can be easily swapped with a different implementation with no impact on the calling code.
4. Readability - Code that's difficult to understand is difficult to change without breaking it.
You may be thinking that it's not possible to automate the checking of code readability, and to some extent that's true. But studies have shown a very strong correlation between the complexity of code and how easy it is to read and understand. For example, code that has a lower Maintainability Index tends to score lower for readability, too.
As well as monitoring code for complexity, Gold Standard dev teams can also monitor the semantic content of their code using an increasingly sophisticated array of Natural Language Processing tools.
Simple applications of well-established readability metrics, like Flesch Reading Ease, can also help draw our attention to difficult code.
And even something as simple as calculating the conceptual correlation between names in our code and words used by our customers to describe the problem domain can help highlight code that may not be "speaking the customer's language".
5. Test assurance - If we made a change that broke the code, how soon would we know? How easy would it be to pinpoint the problem?
This is a crucial factor in the cost of changing code, and one that's usually overlooked in discussions about maintainability. Bugs cost exponentially more to fix the later they're discovered. The goal of automated regression tests is to discover them sooner, which saves us a lot of time.
Gold Standard teams continuously monitor how good their automated tests are at catching regressions. The way they do this is to deliberately introduce errors into their code, and see if any of the tests catch them. This is called mutation testing, and there are tools available for many programming languages that will do it automatically, alerting devs to any gaps in their automated test suites and giving them increased confidence when making changes.
Another key component of test assurance is how often we can run our automated tests. The longer they take to run, the less often we can run them and the longer we have to wait for feedback. Gold Standard teams monitor test execution time and optimise their test suites to run as fast as they need.
And finally, when a test does fail, Gold Standard teams are able to pinpoint the problem and fix it sooner, because their tests typically ask less questions. A Gold Standard automated test suite might cover 100,000 lines of production code with 10-20,000 tests, each having only one reason to fail. LOC/test is a key metric for Gold Standard teams, and they rarely let it go beyond 10 LOC/test.
PS. Shameless plug: If you'd like to learn more about Continuous Inspection, I run a bite-sized training workshop on code craft metrics.
July 10, 2017
Codemanship Bite-Sized - 2-Hour Trainng Workshops for Busy Teams
One thing that clients mention often is just how difficult it is to make time for team training. A 2 or 3-day course takes your team out of action for a big chunk of time, during which nothing's getting delivered.
For those teams that struggle to find time for training, I've created a spiffing menu of action-packed 2-hour code craft workshops that can be delivered any time from 8am to 8pm.
- Test-Driven Development workshops
- Introduction to TDD
- Specification By Example/BDD
- Stubs, Mocks & Dummies
- Outside-In TDD
- Refactoring workshops
- Refactoring 101
- Refactoring To Patterns
- Design Principles workshops
- Simple Design & Tell, Don’t Ask
- Clean Code Metrics
To find out more, visit http://www.codemanship.co.uk/bitesized.html
June 20, 2017
Are.Fluent(Assertions).Really.Easier.To(Understand)?I'm currently updating a slide deck for an NUnit workshop I run (all the spiffy new library versions, because I'm down with the yoof), and got to the slide on fluent assertions.
The point I make with this slide is that - according to the popular wisdom - fluent assertions are easier to understand because they're more expressive than classic NUnit assertions.
So, I took a bunch of examples of classic assertions from a previous slide and redid them as fluent assertions, and ended up with this.
Compared next to each other like this, suddenly somehow my claim that fluent assertions are easier to understand looks shaky. Are they? Are they really?
A client of mine, some time back now, ran a little internal experiment on this with fluent assertions written with Hamcrest and JUnit. They rigged up a dozen or so assertions in fluent and classic styles, and timed developers while they decided if those tests would pass or fail. It was noted - with some surprise - that people seemed to grok the classic assertions faster.
What do you think?
June 5, 2017
The Codemanship TDD "Driving Test" - Initial UpdateA question that gets asked increasingly frequently by folk who've been on a Codemanship TDD workshop is "Do we get a certificate?"
Now, I'm not a great believer in certification, especially when the certificates are essentially just for turning up. For example, a certificate that says you're an "agile developer", based on sitting an exam at the end of a 2-3 day training course, really doesn't say anything meaningful about your actual abilities.
Having said all that, I have pioneered programs in the past that did seem to be a decent indicator of TDD skills and habits. First of all, to know if a juggler can juggle, we've got to see them juggle.
A TDD exam is meaningless in most respects, except perhaps to show that someone understands why they're doing what they're doing. Someone may be in the habit of writing tests that only ask one question, but I see developers doing things all the time that they "read in a book" or "saw their team doing" and all they're really doing is parroting it.
Conversely, someone may understand that tests should ideally have only one reason to fail so that when they do fail, it's much easier to pinpoint the cause of the problem, but never put that into practice. I also see a lot of developers who can talk the talk but don't walk the walk.
So, the top item on my TDD certification wish-list would be that it has to demonstrate both practical ability and insight.
In this respect, the best analogy I can think of is a driving test; learner drivers have to demonstrate a practical grasp of the mechanics of safe driving as well as a theoretical grasp of motoring and the highway code. In a TDD "driving test", people would need to succeed at both a practical and a theoretical component.
The practical element would need to be challenging enough - but not too challenging - to get a real feel for whether they're good enough at TDD to scale it to non-trivial problems. FizzBuzz just won't vut it, in my experience. (Although you can weed out theose who obviously can't even do the basics in a few minutes.)
The Team Dojo I created for the Software Craftsmanship conference seems like a viable candidate. Except it would be tackled by you alone (which you may actually find easier!) In the original dojo, developers had to tackle requirements for a fictional social network for programmers. There were a handful of user stories, accompanied by some acceptance tests that the solution had to pass to score points.
In a TDD driving test, I might ask developers to tackle a similar scale of problem (roughly 4-8 hours for an individual to complete). There would be some automated acceptance tests that your solution would need to pass before you can complete the driving test.
Once you've committed your finished solution, a much more exhaustive suite of tests would then be run against it (you'd be asked to implement a specific API to enable this). I'm currently pondering and consulting on how many bugs I might allow. My instinct is to say that if any of these tests fail, you've failed your TDD driving test. A solution of maybe 1,000 lines of code should have no bugs in it if the goal is to achieve a defect density of < 0.1/KLOC. I am, of course, from the "code should be of high integrity" school of development. We'll see how that pans out after I trial the driving test.
So, we have two bars that your solution would have to clear so far: acceptance tests, and exhaustive testing.
Provided you successfully jump those hurdles, your code would then be inspected or analysed for key aspects of maintainability: readability, simplicity, and lack of duplication. (The other 3 goals of Simple Design, basically.)
As an indicator, I'd also measure your code coverage (probably using mutation testing). If you really did TDD it rigorously, I'd expect the level of test assurance to be very high. Again, a trial will help set a realistic quality bar for this, but I'm guessing it will be about 90%, depending on which mutation testing I use and which mutations are switched on/off.
Finally, I'd be interested in the "testability" of your design. That's usually a euphamism for whether or not dependencies betwreen your modules are easily swappable (by dependency injection). The problem would also be designed to require the use of some test doubles, and I'd check that they were used appropriately.
So, you'd have to pass the acceptance tests to complete the test. Then your solution would be exhaustively tested to see if any bugs slipped through. If no bugs are found, the code will be inspected for basic cleanliness. I may also check the execution time of the tests and set an upper limit for that.
First and foremost, TDD is about getting shit done - and getting it done right. Any certification that doesn't test this is not worth the paper it's printed on.
And last, but not least, someone - initially me, probably - will pair with you remotely for half an hour at some random time during the test to:
1. Confirm that it really is you who's doing it, and...
2. See if you apply good TDD habits, of which you'd have been given a list well in advance to help you practice. If you've been on a Codemanship TDD course, or seen lists of "good TDD habits" in conference talks and blog posts (most of which originated from Codemanship, BTW), then you'll already know what many of these habits are
During that half hour of pairing, your insights into TDD will also be randomly tested. Do you understand why you're running the test to see it fail first? Do you know the difference between a mock and stub and a dummy?
Naturally, people will complain that "this isn't how we do TDD", and that's fair comment. But you could argue the same thing in a real driving test: "that's not how I'm gonna drive."
The Codemanship TDD driving test would be aimed at people who've been on a Codemanship TDD workshop in the last 8 years and have learned to do TDD the Codemanship way. It would demonstrate not only that you attended the workshop, but that you understood it, and then went away and practiced until you could apply the ideas on something resembling a real-world problem.
Based on experience, I'd expect developers to need 4-6 months of regular practice at TDD after a training workshop before they'd be ready to take the driving test.
Still much thinking and work to be done. Will keep you posted.