Look for my updated comments below.
Back in 2008, I wrote a blog post in order to get a free license of TypeMock (now Typemock Isolator). As a result, I got a free license of the product (which I am thankful even though I have not run it a single time) and a “nice” newsletter subscription.
Every now and then, marketing wheels turn and I receive the occasional marketing email that, most often than not, I throw away to the virtual trash without even looking at it. For some reason, this time was not one of them, and I actually had a look at the headers, one of which captured my attention: Unit Test Patterns for .NET.
I read through the article and I recommend you to do the same.
Ready? Finished? Could you make it until the end of it? Lucky you, as you must have a tough stomach. I could not finish it.
As a matter of fact I forced myself to read in its entirety a couple of times. And it was not pleasant. I threw up in my mouth. A little bit…
Let’s start by the beginning
Although Wikipedia is not always the best source for knowledge (particularly computer science-related) it sometimes does a decent job. And the definition of Software Design Pattern is fine enough.
[a design pattern]… is a general reusable solution to a commonly occurring problem within a given context
Cutting the academia I would define it as a scratch to an itch that you can refer by a name so that everyone know what you are talking about. And you can quote me on that.
…patterns are formalized best practices that you must implement yourself in your application
So the reason we pay attention at all to patterns is a) they make us look smarter than we really are and b) they are supposed to be a good thing. For stuff that is not as good, we have another name, which, surprisingly enough is Anti-Pattern, that if we refer to our good enough source of knowledge is
…a pattern that may be commonly used but is ineffective and/or counterproductive in practice
Patterns ≡ good.
Anti-patterns ≡ not so good
That is the part that got my hopes high as it describes what a “good” test must have: isolated, speedy, self-contained, independent, well documented and maintainable.
Very few people can argue that those are not nice to have features in a test. There may be more or others, but those look fine.
It also sets the scenario of each “pattern”: when to use, how to use and a code sample. Juicy bits.
Four-Stage Testing Pattern
Which is a fancy name (and aren’t all pattern names fancy?) for:
- prepare your sh#t
- smoke it
- verify the outcome
- clean your mess
That is pretty prevalent amongst testing frameworks and definitely makes up for a good pattern.
This one started to smell. Not for the pattern itself, which has all the good intentions in the world, but the recommendation of using the
ExpectedExceptionAttribute strikes me as odd, given the existence of pretty ancient blog posts discouraging its usage for a number of reasons:
- it breaks the four-stage pattern (aka Arrange-Act-Assert) by defining the assertion out of order
- it may succeed for the wrong reason, as we assert the entire test, the exception may or may not happen where and when we expect it
- it hurts the readability of the test, more if we want to check more than the type of the exception
- Good intention but a weird example to be shown in 2012.
Inner-Class Test Pattern
At least the previous one had good intentions, but this one even starts badly: “When? When a protected entity needs to be accessed from the tests”.
Why on earth do we want to test a protected method? Wouldn’t it be because the system under test is poorly designed instead? Has the author not heard of encapsulation? Questions, questions…
I have to confess that I have been guilty of this sin (the sin being trying to test internals of an object). I even tried to rationalize it: “My case is more complicated that those stupid oversimplified examples”, “I had to do it, the voices told me to”. But that was quite a few years ago. And I did not write an article published by a supposedly reputed software company that aims to lead within their domain. And I did consider using a different design, but was too lazy/ignorant/pressured to implement it.
Cocky as it sounds, I say there is no reason, in 2012, with many years of baggage in the testing practice and an enormous wealth of knowledge available, why anyone should advocate (remember that patterns are supposed to be good) such a practice. And to add insult to injury, the example code is pretty awful, incomplete and does a poor job communicating the principle.
See my update on this pattern below.
Reflection Test Pattern
And it went downhill without brakes from the previous on, since this does not soothes the problem with the access modifiers balsam. This one goes straight to the meat: “…When we need to test private methods”. Yikes.
And the author might have felt so bad writing it, that added a “…in most cases we don't need to test private methods…”, but the exception to the rule that he describes is laughable.
I guess that the only way left to us, human beings, to test that a binary tree is perfect is by inspecting the internals of the implementation. Of course, traversing the tree and checking the depth of nodes has to be forbidden by a higher authority. And there goes my written sarcasm.
Wait, there Is More
But I stopped here.
There is a Mock-Object pattern in which the author does not even mention the product of the company (which is OK, I suppose) and a Part II article, in which a terrible system under test, plagued with worse-practices (lack of cohesiveness, multiple responsibilities, poor design and the worst advice for implementing logging I have seen) takes advantage of the “virtues” of TypeMock Isolator for saving the “headache” of being properly designed in order to be “tested”. Yay!!
Ok, that was bad, what to do then?
I can understand someone writing poor advices from the lack of knowing better. We all do. But that those harmful advices are published by a company such a Typemock tells a thing or two about the company.
- Technical publications are not being reviewed by technical people. Marketing won. Run hands above heads and place your wallet in a safe place.
- If technical articles are reviewed by junior technical people, send those reviewers to a decent course (hell, even I could give them some training for free –or peanuts–). I hope TypeMock still has a couple of brilliant guys that can agree with me that “this is not good enough for us”.
- If technical articles are reviewed by senior technical people, fire them. Get rid of those before they get their hands deeper in your code base. God bless their families.
- Techy-writing was reviewed, reviewers complained but it was published anyway. Which is another flavor of “Marketing won” that yields the same outcome.
- In a twisted scenario: let’s put something together something about patterns (they are good and fashionable) that can be implemented painlessly by our product and present the product as the savior that can save you money in the short term by giving you the false sense of security that testing abominations can provide which will be a money sink in the future when our license fee is already paid.
But that would be too twisted, wouldn’t it?
Be reality any of the above scenarios or any other one can invent to justify the publication of such material, articles like these hurt the credibility of the company that publishes them, they do a disservice for the product they are supposed to be marketing and, in the hands of someone who accepts them uncritically, they are plainly dangerous and their publication irresponsible.
Lobby with me to eradicate misguided articles. At least the technical ones.
Politics articles are a lost cause anyway.
UPDATE: It turns out that, in my solitude of the morning shower (what a great place to think over the things you did yesterday and visualize the ones you are going to do today) I came up with a valid scenario in which you would “need” to test a protected method, that is a valid scenario for the Inner-Class Test Pattern.
Imagine you are an API developer and you provide a class with a virtual method that is not called anywhere but in the possible inheritors that API consumers might create. In that case you would want to test what the method does and the way to do it is surfacing the method in a test class. You are walking a thin line here, but I would consider that such virtual method is part of the “public” interface of such an class and thus subject to test.
This correction does not affect the author of the article as none of the cases or examples he provides are, in my opinion, valid cases in which one can implement such a rare pattern.