TDD assignment for beginners?
I want to introduce the Test Driven Development discipline to my junior Java programmers, who have never heard the term before. I plan to conduct a session that explains the basics and benefits of TDD in first half, and then walks through a hands-on assignm开发者_运维百科ent in the second half.
So what could be a good, Java based, assignment for giving it to TDD novices? It should not be so trivial that people lose interest, and not so difficult that they lose heart. I have seen a few on the net, but also want to consider your suggestions. Any pointers/links on the same are greatly appreciated.
Here is a non-trivial TDD tutorial where the topic is writing Tetris. It will probably take over 10 hours to finish it. About 30 of the first tests have been pre-written and after that some hints have been provided on what tests to write next.
https://github.com/orfjackal/tdd-tetris-tutorial
An example I love to use in demonstrating TDD is a password strength validator: write some code that checks whether a string is a sufficiently strong password. I like it because:
- everyone understands the problem, and it's not language specific
- you can start with one or two rules that are easy to test for (is not "PASSWORD", has more than 8 characters...) to get the hang of the TDD rhythm
- you quickly get into interesting questions when you have 2 or more rules. Testing becomes hard and leads to a re-design/re-factoring, separating the rules from the validator, and getting code that is both clean and easy to test.
I like Range for this - just a range of integers. Write includes(int), overlaps(Range), and any similar methods; you get to figure out whether it's full-open, full-closed, or half-open (the best answer, mostly), and let the tests drive you there.
Also good is Natural Sort. Practical, useful, and test-driving it can lead you to unexpected solutions.
I love writing engines to John Conway's Game of Life.
Very simple rules. They can be written in one (slightly messy) class, but the real joy is when you start thinking about the responsibility of classes, then mock out those responsibilities - for instance, neighbourhood calculator, rules, etc.
You can also drive out a better design with a few extra rules:
- The grid can be switched back and forth at run-time from a bounded grid (outside which nothing can survive) to an infinite grid or a wrapped grid (gliders come back on the other side).
- The cells change color (or string representation) depending on how old they are (moves the design from a value object to an entity).
- The rules can be changed from Conway's to High Life.
If you're working graphically as well you can have even more fun. Developers can use tests or scenarios to talk through edge-cases (interaction between the various stories gets complex):
- Cells change size depending on the number of neighbours
- There's a "back" button
- There's a joystick which enables you to navigate around wrapped or infinite grids
- The board can be (re)set to predefined scenarios
- The board can change size.
This is what Corey Haines always uses on his Code Retreats. I've used it for teaching TDD / unit-level BDD for years. You can get to see some progress very quickly, then it gets trickier as it grows.
I used incremental search in more than one class with great results. People know this scenario from their cell phones; the address book usually works this way (you type the beggining of a name and it displays all names starting with those letters).
One advantage is that this problem can be really incremental. You get to know the details when you're already doing it. And you can add extras, like:
- most recently used behavior (the most searched names appear first): this requires the incremental search object to store state
- alphabetical ordering
- considering letters at any position (e.g., searching for "JSm" finds "John Smith")
However, if you're doing it on class, I recommend that you have about 3 hours available. It is not a quick example. And it deals a lot with lists, so make sure your students are familiar with them, including Arrays.asList, preferrably.
Tic-tac-toe game. Have the player go first, computer go second.
You can start with the computer always going in the middle, but then you need a test to make sure the computer doesn't pick a spot that is already taken. Then you can slowly work up to testing to make sure the computer always covers its vulnerabilities.
(not an answer, just commenting. please ignore.)
Testing should not be the center of programming. Especially for young students. Whenever we can, we should first focus intensely on the logic and reasoning of the implementation. We should practice our skills to such confidence that we know the code is correct, simply because we wrote it.
Is that an improbable goal? Many people can actually approach it very closely. But even if it's too unreachable for a person, he should practice this way at least when he's a student. It won't hurt.
In TDD, it seems to encourage students to do a good enough job to pass the tests. You don't really have to think carefully about your algorithm; just tweak it until it passes the tests, which is quite easy.
Everything bad will come out of it.
I'm not saying testing is not important. But it should not be the 1st line of defense for correctness.
In another related topic, some people argue that TDD is good for design: if a code is easy to test, it's very likely a good design. That's also very puzzling - when can't one directly focus on good design?
精彩评论