Found in 3 comments on Hacker News
BeetleB · 2018-08-31 · Original thread
Depending on the language:

Unit testing is easy for beginners. Unit testing done well is much less so. This results in many inexperienced people writing poor unit tests.

In my last job, I worked on a legacy C++ code base. 500K lines of thorough testing, but none was a unit test. It took 10 hours to run the full test suite. I set about the task of converting portions for unit testability.

I was surprised how much of a challenge it was (and I learned a lot). There were few resources on proper unit testing in C++. Mostly learned from Stack Overflow. Lessons learned:

1. If your code did not have unit tests, then likely your code will need a lot of rearchitecting just to enable a single unit test. The good news is that the rearchitecting made the code better.

As a corollary: You'll never know how much coupling there is in your code until you write unit tests for it. Our code looked fairly good, but when I wanted to test one part, I found too many dependencies I needed to bring in just to test it. In the end, to test one part, I was involving code from all over the code base. Not good. Most of my effort was writing interface classes to separate the parts so that I could unit test them.

2. For C++, this means your code will look very enterprisey. For once, this was a good thing.

3. Mocking is an art. There's no ideal rule/guideline for it. Overmock and you are just encoding bugs into your tests. Undermock and you are testing too many things at once.

4. For the love of God, don't do a 1:1 mapping between functions/methods and tests. It's OK if your test involves more than one method. Even Robert Martin (Uncle Bob) says so. I know I go against much dogma, but make your unit tests test features, not functions.

5. If your unit tests keep breaking due to trivial refactors, then architect your unit tests to be less sensitive to refactors.

6. For classes, don't test private methods directly. Test them through your public interface. If you cannot reach some code in a private method via the public interface, throw the code away!

7. Perhaps the most important: Assume a hostile management (which is what I had). For every code change you make so that you can write a unit test, can you justify that code change assuming your project never will have unit tests? There are multiple ways to write unit tests - many of them are bad. This guideline will keep you from taking convenient shortcuts.

This advice is all about unit tests, and not TDD. With TDD, it is not hard to test yourself into a corner where you then throw everything away and restart. If you insist on TDD, then at least follow Uncle Bob's heuristic. For your function/feature, think of the most complicated result/boundary input, and make that your first unit test. This way you're less likely to develop the function into the wrong corner.

When I completed my proof of work, the team rejected it. The feedback was it required too much skill for some of the people in the team (40+ developers across 4 sites), and the likelihood that all of them will get it was miniscule. And too much of the code would need to change to add unit tests.

I later read this book:

And it contains quite a bit of what I learned from unit testing.

W0lf · 2017-06-05 · Original thread
I've gathered all the book titles in this thread and created Amazon affiliate links (if you don't mind. Otherwise you still have all the titles together :-) )

A Pattern Language, Alexander and Ishikawa and Silverstein

Advanced Programming in the Unix Environment , Stevens

Algorithmics: the Spirit of Computing, Harel

Applied Crytography, Wiley

Clean Code, Martin

Clean Coder, Martin

Code Complete, McConnel

Code: The Hidden Language of Computer Hardware and Software, Petzold

Coders at Work, Seibel

Compilers: Principles, Techniques, & Tools, Aho

Computer Systems: A Programmer's Perspective, O'Hallaron and Bryant

Data Flow Analysis: Theory and Practice, Khedker

Dependency Injection in .NET, Seemann

Domain Driven Design, Evans

Fundamentals of Wireless Communication, Tse and Viswanath

Genetic Programming: An Intrduction, Banzhaf

Head First Design Patterns, O'Reilly

Implementing Domain-Driven Design, Vernon

Intrduction to Algorithms, CLRS

Introduction to General Systems Thinking, Weinberg

Joy of Clojure, Fogus and Houser

Let over Lambda, Hoyte

Operating Systems: Design and Implementation, Tanenbaum

Parsing Techniques, Grune and Jacobs

Peopleware: Productive Projects and Teams, DeMarco and Lister

Programming Pearls, Bentley

Software Process Design: Out of the Tar Pit, McGraw-Hill

Software Runaways, Glass

Sorting and Searching, Knuth

Structure and Interpretation of Computer Programs, Abelson and Sussman

The Art of Unit Testing, Manning

The Art of Unix Programming, ESR

The Design of Design: Essays from a Computer Scientist, Brooks

The Effective Engineer, Lau

The Elements of Style, Strunk and White

The Healthy Programmer, Kutner

The Linux Programming Interface, Kerrisk

The Mythical Man-Month, Brooks

The Practice of Programming, Kernighan and Pike

The Pragmatic Programmer, Hunt and Thomas

The Psychology of Computer Programming, Weinberg

Transaction Processing: Concepts and Techniques, Gray and Reuter

Types and Programming Languages, Pierce

Understanding MySQL Internals, Pachev

Working Effectively with Legacy Code, Feathers

Zen of graphics programming, Abrash

douche · 2016-07-19 · Original thread
In my opinion, the way Manning does this is pretty close to ideal. If you buy a physical copy of, say The Art of Unit Testing[1], or C# in Depth[2], either directly from them, Amazon, a bookstore, whatever, you get a code to download the ebook as well. Especially because it is usually only about $10 more expensive to buy the physical book + ebook combo, rather than just the ebook from them.



Fresh book recommendations delivered straight to your inbox every Thursday.