Blog Archive for / 2006 /
Mocks, Stubs, Fakes and Interaction-based Testing
Monday, 04 December 2006
There has been extensive discussion on the Test-Driven Development Yahoo group recently about state-based testing, interaction-based testing, and the use of Mocks and other Test Doubles. I tend to use quite a lot of test doubles in my tests, so I thought I'd explain why.
I find that using various forms of test doubles whilst doing TDD can greatly speed my development, as it allows me to focus on the class under test, and its interaction with the rest of the system.
I tend to use a test double for any part that's not directly related to the responsibility of the class under test. For example, if I'm testing something that needs to send an email, then I will use a dummy smtp client, which just logs the email for examination in the test, rather than actually sending it. If I need a class to encrypt something, I will provide a dummy encryption algorithm, and verify that the class under test encrypts the correct data, and correctly uses the encrypted output, rather than using a real encryption algorithm, which may produce output with an element of randomness, and which cannot therefore be readily used in an assertion.
Not only does this make testing easier, since it provides for greater isolation, and more focused tests, but the resultant separation of concerns is good for the overall design — rather than relying on a particular concrete implementation, the class under test now relies on an abstract interface. This reduces coupling, and increases cohesion. It also makes it easier to reuse code — lots of small classes, with well-defined responsibilities, are much more likely to be useful elsewhere.
Though I would tend to call my test implementations of these interfaces "mocks", the term "Mock" has come to mean a quite specific type of implementation, where the user sets "expectations" on which member functions will be called, with which parameters, and in what order; the Mock then verifies these expectations, and asserts if they are not met. Many "Mock Objects" are also automatically derived, commonly by using reflection and fancy "Mock Object Frameworks". My test implementations rarely do these things, and are probably better described as "Stubs", "Fakes", or even something else. I'm coming to like "dummy" as in "Crash Test Dummy" — it's not a crash that we're testing, but the "dummy" does provide information about how the class-under-test behaved, and allows the test to specify responses to stimuli from the class-under-test, and therefore exercise particular code paths in the class-under-test.
Going back to my sending-email example above — by using a dummy implementation, the tests can check the behaviour of the class under test when the email is sent successfully, and when it is not. The test can also verify that it is sent at all, and with the correct contents.
Furthermore, I generally don't write a separate class for the dummy implementations — I use the "Self Shunt" pattern, and make the test-case class server double-duty as the dummy implementation. This has the added benefit that I don't have to explicitly pull any data out of the dummy class, as it's already right there in the test — the dummy functions can just store data directly in the member variables for the tests to use.
The real question, as ever, is where to draw the line between using real code, and providing dummy implementations; the extremes are easy, it's the in-between cases that require more thought. If the code talks to an external system (remote server, database, filesystem, etc), then for TDD-style tests, it's probably best to provide a dummy implementation. Likewise, at the other extreme, you have to have a real implementation of something in order for the test to be worthwhile.
I tend to draw the line along where I think the division in responsibility lies — if the code needs to send an email in response to certain conditions, then there are two responsibilities: sending an email, and making the decision to do so based on the conditions. I would therefore have two classes, and two sets of tests. One class will actually unconditionally send an email, in which case I would provide a dummy implementation of an SMTP server under control of the tests, and have the class under test connect to it as-if it was a real SMTP server. In this case, the dummy will have to implement the full SMTP protocol, though the responses might be hard-coded, or depend on what aspect is being tested.
The second responsibility (deciding to send an email) belongs in a separate class, and the tests for this would provide a dummy implementation of the email-sending interface, so there's no network traffic required. I would (and have done where this has been required) probably develop this class first, in order to isolate precisely what interface is needed for the email-sending class, unless I already had an email-sending class that I was hoping to reuse, in which case I would start with the interface to that as it stood, and refactor if necessary.
Posted by Anthony Williams
[/ tdd /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
V1.2 of the dbExpress drivers for MySQL V5.0 released
Tuesday, 28 November 2006
New this release:
- Now works with TSQLTable
- Support for
DecimalSeparator
other than'.'
- Support for the
ServerCharSet
connection parameter in BDS2006 - Now correctly retrieves empty binary data fields
See the download page for more details.
Posted by Anthony Williams
[/ delphi /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Vector-based Bowling Scores in C++
Tuesday, 02 May 2006
Introduction
In one of his recent articles, Ron Jeffries looks at a vector-based method of calculating scores for Tenpin bowling. He uses Ruby, and makes two comments which inspired me to redo it in C++.
First, he says:
To begin with, did you notice that every method is only one line long? That's a characteristic of good Smalltalk code, and good Ruby code, in my opinion. You can't get there in Java or C# -- much less C++
I disagree — good C++ will have short functions, and many will only be one line. This is borne out by my sample code.
Ron also says:
I'm not sure what would happen if we tried to build a vector-oriented solution in Java or C#. I'm sure it would be larger, and that we'd have to put a bunch of code in "our" classes instead of in Array and Object. On the other hand, I'm confident that we could have our score method look very much like the one we have here, processing the vectors "all at once" in a very similar way.
I'm using C++ rather than Java or C#, but I hope Ron will still be
interested. I did write versions of accumulate
that accept a whole
vector at once, rather than requiring a pair of iterators, but otherwise it's
all idiomatic C++.
Discussion
As you can see from the code (below), there is only one functions which is
more than one line long. This is Game::frame_starts
, and the reason
for this is the lack of the built-in numeric range generation one gets with
Ruby's 1..9
syntax. With such a mechanism, we could make it
similar to Game::frame_scores
.
Given the range-based versions of accumulate
I've added, we
could add make_numeric_range
to return a range containing the
required integers, so Game::frame_starts
could be made one line,
but the code for this would end up being longer than
Game::frame_starts
is at the moment.
Of course, as Game::frame_scores
demonstrates, the code has to
go somewhere — in the case of Game::frame_scores
, this is the
nested class Game::AddFrameScore
, and its
operator()
. If C++ had lambdas (which hopefully it will, when the
next standard comes out), then we could include this code directly in the call
to std::accumulate
, but as it is, we need a whole new class. Member
classes don't have the access to the instance members of their parent class that
Java's inner classes enjoy, so we need to keep the reference to the
Game
object explicitly.
At 75 lines, including blank lines, the code is only marginally longer than the 72 lines for Ron's Ruby version, and just as clear, to my mind.
The code
Here it is, in all its glory. First the implementation:
#include <numeric> #include <vector> template<typename Range,typename Accum> Accum accumulate(Range const& range,Accum initial) { return std::accumulate(range.begin(),range.end(),initial); } template<typename Range,typename Accum,typename Pred> Accum accumulate(Range const& range,Accum initial,Pred pred) { return std::accumulate(range.begin(),range.end(),initial,pred); } class Game { std::vector<unsigned> rolls; struct AddFrameScore { Game const& game; explicit AddFrameScore(Game const& game_): game(game_) {} std::vector<unsigned> operator()(std::vector<unsigned> res,unsigned first_roll) { return res.push_back(game.frame_score(first_roll)), res; } }; public: static unsigned const frame_count=10; template<unsigned Size> explicit Game(unsigned const(& rolls_)[Size]): rolls(rolls_,rolls_+Size) {} unsigned score() const { return accumulate(frame_scores(),0); } unsigned is_strike(unsigned first_roll) const { return rolls[first_roll]==10; } unsigned is_spare(unsigned first_roll) const { return (rolls[first_roll]+rolls[first_roll+1])==10; } unsigned is_mark(unsigned first_roll) const { return is_strike(first_roll) || is_spare(first_roll); } unsigned rolls_to_score(unsigned first_roll) const { return is_mark(first_roll)?3:2; } unsigned rolls_in_frame(unsigned first_roll) const { return is_strike(first_roll)?1:2; } unsigned frame_score(unsigned first_roll) const { return std::accumulate(&rolls[first_roll],&rolls[first_roll+rolls_to_score(first_roll)],0); } std::vector<unsigned> frame_starts() const { std::vector<unsigned> res; for(unsigned i=0;res.size()<frame_count;i+=rolls_in_frame(i)) { res.push_back(i); } return res; } std::vector<unsigned> frame_scores() const { return ::accumulate(frame_starts(),std::vector<unsigned>(),AddFrameScore(*this)); } };
And now the tests:
#include <algorithm> #include <iostream> #define ASSERT_EQUALS(lhs,rhs) \ { \ if(lhs!=rhs) { \ std::cerr<<__FILE__<<": "<<__LINE__ \ <<": Error: Assertion failed: " #lhs "==" #rhs ", lhs=" \ <<lhs<<", rhs="<<rhs<<std::endl; \ } \ } template<typename T> std::ostream& operator<<(std::ostream& os,std::vector<T> const& vec) { os<<"{"; for(typename std::vector<T>::const_iterator it=vec.begin(), end=vec.end(); it!=end; ++it) { os<<*it<<","; } return os<<"}"; } template<unsigned Size> std::ostream& operator<<(std::ostream& os,unsigned const (& vec)[Size]) { os<<"{"; for(unsigned i=0;i<Size;++i) { os<<vec[i]<<","; } return os<<"}"; } template<typename LhsRange,unsigned RhsRangeSize> bool operator!=(LhsRange const& lhs,unsigned const(& rhs)[RhsRangeSize]) { return (std::distance(lhs.begin(),lhs.end()) != RhsRangeSize) || !std::equal(lhs.begin(),lhs.end(),rhs); } int main() { unsigned const full_game_rolls=20; unsigned const all_zeros[full_game_rolls]={0}; ASSERT_EQUALS(Game(all_zeros).score(),0); unsigned const all_open[]={1,2,2,6,3,2,4,1,5,4,6,0,7,2,8,0,9,0,0,2}; ASSERT_EQUALS(Game(all_open).score(),64); unsigned const all_open_frame_starts[]={0,2,4,6,8,10,12,14,16,18}; ASSERT_EQUALS(Game(all_open).frame_starts(),all_open_frame_starts); for(unsigned i=0;i<full_game_rolls;i+=2) { ASSERT_EQUALS(Game(all_open).rolls_to_score(i),2); } unsigned const spare[full_game_rolls]={6,4,6,2}; ASSERT_EQUALS(Game(spare).rolls_to_score(0),3); ASSERT_EQUALS(Game(spare).rolls_to_score(2),2); unsigned const all_open_frame_scores[Game::frame_count]={3,8,5,5,9,6,9,8,9,2}; ASSERT_EQUALS(Game(all_open).frame_scores(),all_open_frame_scores); unsigned const spare_frame_scores[Game::frame_count]={16,8}; ASSERT_EQUALS(Game(spare).frame_scores(),spare_frame_scores); ASSERT_EQUALS(Game(spare).score(),24); unsigned const strike[full_game_rolls-1]={10,6,2}; ASSERT_EQUALS(Game(strike).rolls_to_score(0),3); ASSERT_EQUALS(Game(strike).rolls_to_score(1),2); unsigned const strike_frame_starts[]={0,1,3,5,7,9,11,13,15,17}; ASSERT_EQUALS(Game(strike).frame_starts(),strike_frame_starts); unsigned const alternating[]={10,1,9,10,1,9,10,1,9,10,1,9,10,1,9,10}; ASSERT_EQUALS(Game(alternating).score(),200); unsigned const all_strikes[]={10,10,10,10,10,10,10,10,10,10,10,10}; ASSERT_EQUALS(Game(all_strikes).score(),300); }
Posted by Anthony Williams
[/ cplusplus /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Message Handling Without Dependencies
Wednesday, 19 April 2006
My article, Message Handling Without Dependencies has been published in the May 2006 issue of Dr Dobb's Journal.
In the article, I describe a technique using templates and virtual functions to reduce dependencies when passing messages in C++. I have used this technique to great effect in production code.
Posted by Anthony Williams
[/ news /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Refactoring to Patterns by Joshua Kerievsky
Wednesday, 12 April 2006
The opening chapters cover the background, introducing both refactoring and design patterns, and the context in which the book was written. This gives the reader a clear overview of what is involved in Refactoring to Patterns, and paves the way for the refactoring catalogue which makes up the bulk of the book.
The catalogue is divided into chapters based on the type of change required — is this a refactoring to simplify code, generalize code, or increase encapsulation and protection? Each chapter has an introduction which gives an overview of the refactorings contained within that chapter, followed by the refactorings themselves. These introductions clearly illustrate the principles and choices which would lead one to follow the refactorings that follow.
Each refactoring starts with a brief one sentence summary, and before and after structure diagrams with reference to the structure diagrams for the relevant pattern in the Design Patterns book. The sections that follow then cover the Motivation for using this refactoring, step-by-step Mechanics, and a worked Example, relating back to the steps given for the Mechanics. Finally, some of the refactorings finish with Variations on the same theme. The examples are all pulled from a small sample of projects, which are introduced at the beginning of the catalogue section, and help illuminate the instructions given in the Mechanics section. The mechanics themselves are generally clear, and broken down into small steps — sometimes smaller steps than I might take in practice, but I think this is probably wise, as large steps can easily confuse. Finally, the Motivation sections do a good job of explaining why one would choose to do a particular refactoring, and any pitfalls to doing so — the "Benefits and Liabilities" tables provide a useful summary.
This book is well written, easy to read, and genuinely useful. It has helped me put some of the refactorings I do into a larger context, and given me insight into how I can integrate patterns with existing code, rather than designing them in up front. As John Brant and Don Roberts highlight in their Afterword, this is a book to study, the real benefit comes not from knowing the mechanics, but by understanding the motivation, and the process, so that one may apply the same thinking to other scenarios not covered by this book. If you are serious about software development, buy this book, inwardly digest it, and keep it by your side.
Highly Recommended.
Buy this book
Refactoring to Patterns
Joshua Kerievsky
Published by Addison-Wesley
ISBN 0-321-21335-1
Buy from Amazon.co.uk
Buy from Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Working Effectively With Legacy Code by Michael C. Feathers
Wednesday, 12 April 2006
A lot of the book is spent covering different techniques for getting nasty convoluted code under test. These techniques often focus on breaking dependencies, so you can instantiate an object in a test harness, or call a function without it sending an email or talking to the database. In many cases, these are sensible recommendations for improvements to the codebase, but in some cases, Michael recommends techniques you wouldn't expect to see in production code, such as defining preprocessor macros with the same name as functions to avoid calling them, or writing dummy implementations of API functions. This is not to say that the book recommends such techniques wholesale — Michael is keen to point out that these techniques should only be used to get the code under test, so that it can be refactored safely.
Chapters are helpfully named, with titles like "This class is too big, and I don't want it to get any bigger", and the book gives good advice on how to deal with the nastiest codebases. The key recommendation underlying it all is "get the code under test, so you can refactor safely", and this is borne in mind with those techniques that require changing the production code in order to get it under test — these techniques provide step by step instructions to help you make the required changes without breaking anything.
The content of this book is excellent, and the writing clear, so it is unfortunate that it is marred by numerous minor errors, such as spelling mistakes, or using the wrong identifier when referring to a code example. However, this minor niggle is not enough to stop me recommending it — every software developer should have a copy.
Highly Recommended. This book is a must-have for anyone who has to maintain code — which is pretty much every software developer on the planet.
Buy this book
Working Effectively With Legacy Code
Michael C. Feathers
Published by Prentice Hall PTR
ISBN 0-13-117705-2
Buy from Amazon.co.uk
Buy from Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Extreme Programming Adventures in C# by Ron Jeffries
Tuesday, 14 February 2006
The project is not just one big success story; Ron shares his mistakes with us so that we may learn from them. The book is interspersed with "lessons", where Ron reflects on the preceding section and tries to identify important points, either things that he felt worked well, or things the mistakes he made, and what he thinks could be done to try and avoid similar mistakes . Also throughout the book are sentences marked "sb", for "sound bite". These are short phrases which summarise a point, like "It's Chet's fault" (don't focus on finding who's at fault when things go wrong, rather focus on fixing the problem), or "You Aren't Gonna Need It" (focus on what needs doing now, rather than what you think you'll need for later). It is these lessons and sound bites which provide the "message" of the book — Ron's belief that incremental development, done test-first, with simple design, continuous refactoring and a focus on producing value for the customer is an effective method of producing high quality software.
If you like Ron's other writing you'll love this book. If you've never read Ron's stuff before and are interested in learning a bit about how he applies the principles of XP (and maybe a little C#), it's worth reading; you might even enjoy it.
Highly Recommended.
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of JUnit Recipes: Practical Methods for Programmer Testing by J. B. Rainsberger
Tuesday, 14 February 2006
The book is laid out into a series of chapters describing related techniques, such as "working with test data" and "testing web components", with each chapter split into a series of "recipes", each describing a particular technique. The layout of each recipe is good, with a problem statement, additional background, the details of the recipe itself, and further discussion. There are also references to other related recipes, that provide alternatives to, build on, or are relied on by this recipe.
The level of coverage is very comprehensive. Having read the book it feels like there is a recipe for testing just about everything you could write in Java, from simple classes, to XML generation code, database access code, EJBs, singletons, and JSPs. There are even recipes on managing your test suites, adding tests to hard-to-test classes, and the use of test implementations of other objects to allow testing objects in isolation.
Just because it focuses on Java and JUnit does not mean that this book is useless to anyone programming in another language. On the contrary, many of the techniques described can be applied in any Object Oriented language, though there are certainly some that are specific to Java. For this reason, I would highly recommend this book not just to Java programmers, but to anyone interested in improving the testing of their code.
Highly Recommended.
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Agile Modeling: Effective Practices for eXtreme Programming and the Unified Process by Scott Ambler
Wednesday, 08 February 2006
The book is divided into 5 parts. The first two parts cover the principles you should work to and practices you should be doing to say that you are doing Agile Modeling as Scott defines it. The values of Agile Modeling are the four values of eXtreme Programming, plus a fifth (Humility), and the principles and practices are then derived from applying these values to a modelling perspective. For example, the value of Courage leads one to Discard Temporary Models, and the values of Humility and Communication lead one to realise that Everyone Can Learn From Everyone Else, and that you should Model With Others. This description of the principles and practices forms the real meat of the book. Most (perhaps all) of what Scott says here is sensible advice which should be followed by anyone pursuing an Agile approach to software development.
The remaining parts describe the how Agile Modeling fits into XP and the Universal Process, with a discussion on introducing Agile Modeling into your process. This also includes a discussion of when Agile Modeling is *not* a good fit, as well as a check list of things you must be doing to say you are Agile Modeling, and a list of things which you must not be doing if you want to say you are Agile Modeling. The book finishes off with an appendix listing a host of modelling techniques to consider when the need arises; Scott is quite clear that you need to Apply the Right Artifact, and having a wide range to choose from makes this easier since you are not stretching a model beyond what it can easily cover.
If you are interested in modelling, and want to know how it fits into Agile projects, or you are looking to make your current process more Agile by reducing unnecessary modelling work, then this book is well worth a read; I just wish it was easier to read.
Recommended.
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Agile Documentation: A Pattern Guide to Producing Lightweight Documents for Software Projects by Andreas Rueping
Wednesday, 08 February 2006
The title of this book is "Agile Documentation", but almost everything it says is applicable to documentation for any project, whatever methodology is used. Indeed, much of what is said is common sense if you think about it — but how often does anyone really think about it? Reading this book forces the issue, and hopefully encourages one to think about the purpose, readership and content of documentation a bit more in the future. However, some of the content is particularly important when trying to use an Agile development method, since it contributes to reducing the effort that is wasted on unused or unnecessary (or even unusable) documentation, whilst ensuring that the documentation that is produced is both necessary and sufficient for the project's needs.
The subtitle is "A pattern guide for producing lightweight doucments for software projects", which is quite apt. Essentially, the book consists of a set of patterns, divided into 5 groups, each of which describes a particular problem associated with documentation, and some discussion of the solutions. The key points are summarised in what the author calls "thumbnails" — a couple of sentences which appear in bold type in the pattern description, and which are then repeated in the "thumbnails" section at the back of the book. These enable you to browse through the book, reading each pattern heading and the corresponding thumbnail to get an overview of the pattern and determine whether it is applicable for your current situation, or jog your memory.
The patterns are not just presented on their own, they are backed up by experience reports from a number of projects that the author has been involved with. These are used both within the pattern descriptions, and in a separate section at the end of each chapter. They are not all positive, and are used to highlight the dangers of not following the patterns from the book, as well as the benefits of doing so. Overall, they give the advice a place of reference, and are the source of numerous examples.
One slight issue I had with the book was the number of typos, which was particularly unexpected given the subject matter. However, this did not detract too significantly from my overall impression: Highly Recommended
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Lean Software Development: An Agile Toolkit, by Mary Poppendieck and Tom Poppendieck
Wednesday, 01 February 2006
The book divides lean thinking into 7 key principles, with 22 "tools" to help you adapt agile practices to your workplace. It also features a "try it out" section at the end of each chapter taking you through some simple steps that demonstrate how the particular techniques discussed can be applied to improve your software development process.
Some of these principles are obvious at first glance — "Eliminate Waste" for example — but this simplicity hides profound insight; in this case, the insight is that much of the "work products" of traditional software development processes are in fact waste, produced purely so the developer can "tick the box" and move onto the next task. Not only that, but the very process can itself generate waste — having analysts produce specs from customer requirements, which designers then turn into a high level design for coders to turn into software is very wasteful, because knowledge is lost at every stage; the very act of writing something down means that the understanding and background knowledge held by the author is lost, either permanently, or until the reader has acquired it for himself.
This book is aimed at project managers and lead developers looking for ways to improve their software development process, but I would recommend it to anyone who is serious about producing quality software. Whilst many agile practices require management buy-in (and if you can get your manager to read this book, it will probably help), others can be implemented by developers as part of almost any process.
Buy this book
At amazon.co.ukAt amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of C++ Coding Standards: 101 Rules, Guidelines and Best Practices, by Herb Sutter, Andrei Alexandrescu
Wednesday, 01 February 2006
In contrast with other books from Addison Wesley, such as Effective STL, which have a much easier-to-read layout, but in common with the other books in the C++ In Depth series, the text is slightly too small, and the margins slightly too narrow, so there is too much text on a page. This, combined with the high density of technical content, makes it hard to read cover to cover in one go. There are also a couple of errors; though nothing major, they do detract from the authority of the book, given the nature of the content.
In the preface, the authors state that they intended each item to be short, non-controversial, authoritative, and something that needs saying, and I believe they have achieved that. In any set of coding standards I usually find something that I disagree with, but there was not a single item that grated on me here. I agree with the authors that this book is something you should reference from your own coding standards.
Highly Recommended.
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Review of Test Driven Development - A Practical Guide, by Dave Astels
Wednesday, 01 February 2006
Most of the book uses Java as the target language, and it does appear that the majority of tools available are for Java. However, that does not mean that the techniques discussed are not applicable to other languages; there are chapters in this book dedicated to the use of the "xUnit" testing framework for various languages "x" — such as C++, Python, and Visual Basic.
The main thrust of TDD is that you write tests for the expected behaviour of the production code before you write the code, and that you don't add new code to the system except in response to a failing test. This takes some getting used to, but the key benefit is that you get a high-coverage automated test suite which automatically tells you if you break something when you make a modification.
As programmers, we all know that automated unit tests are a Good Thing, but writing tests after the fact is difficult, and seems like a chore since we already "know" the code works. TDD is not like that. I've been trying it on my latest project, and I am now "test infected" — I'd rather work this way than how I worked before. Applying the techniques discussed in the book to C++ was relatively straightforward; with the help of a few editor macros, adding a new test takes just two key presses, and I've managed to add the automated tests to the build script, so they appear as compile errors in the IDE.
I would recommend this book to all developers, especially those who find writing tests tedious or unnecessary, and those who wish they had a better set of tests when modifying code. Though TDD is one of the key techniques used in Agile methodologies, it can be used under any methodology, since it just replaces the developer tests that most developers would like to have anyway (but probably don't).
Highly Recommended.
Buy this book
At Amazon.co.ukAt Amazon.com
Posted by Anthony Williams
[/ reviews /] permanent link
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy