Measuring code coverage is often perceived as a good measure of test quality. It is not. Good tests finds problems when changes are made to the code. But if you just want to have large code coverage you can easily make a number of tests calling all your methods but not checking the results. The only thing high code coverage values really tell you is that the code is at least not crashing with the given input.
If you however are using BDD/TDD, code coverage values might be of interest. For example if you do not have 100% function coverage (i.e. not 100% of the functions are called) then you aren't really using BDD/TDD are you? Because how could you write a method that is not called by anyone? Well actually you might have created methods that are never called by your tests. Many TDD practitioners use a rule "to simple to test" which applies to real simple, property like methods. I don't really like that philosophy, but more on that in a later post.
So now you think with 100% function coverage you will also have 100% line coverage with BDD/TDD, right? Well, yes and no. Typically you don't since you will add error handling with logging methods that will never occur since the errors never occur in your tests. It might be that you open a file and if that fails you log an error and exit your application. This never happens in the tests since you always manage to open the file in your tests. So how did those lines get in there if never called? Well one other rule often used by TDD practitioners is that you "should not do stupid things". If a system call may fail, you check the result regardless of tests or not. With dependency injection you'll probably get close to 100% but there is no point in bending back-wards in order to achieve high code coverage.
Does this mean there is no point in measuring code coverage? I think it is great to measure code coverage if you use the result correctly. You should not add more tests just to increase coverage since test added just to increase coverage tend to just exercise code and not really testing something interesting. But low code coverage when using BDD/TDD is definitely a warning signal that something is wrong. The team is not using the methodology correctly. So what is considered OK coverage levels? From personal experience I think anything below the levels listed in the table below should be considered bad since type without injectiontype withoutinjection with with you should have no problem at all achieving the given values.
But sometimes there is someone (usually a manager) that thinks coverage should be above some level. So even though you know those tests will not really be useful you have to add more tests for coverage. What do you do? Either you can try to ignore the coverage fact and just try to add more tests, testing interesting things. Or you could try using Pex. Pex is a tool from Microsoft Research that is an automated exploratory testing tool. It can be used to make a small test suite with high code coverage and with only a few simple examples I get the impression it is quite good at finding border cases in your code. This will not however replace your traditional tests/specifications written as part of your TDD/BDD process. But it can help you test some cases you did not think of and that way increase code coverage even more without any extra effort from you. At least it is better than adding coverage tests by hand.
And if you listened to me and started to write nice looking SQL, maybe you wanna look ate making your C# code look nice too...
I read this article on SQL Code Layout and Beautification and can only agree with the author that other people's SQL often is hard to understand because I'm so used to how I write my SQL statements. One of the links is to an on-line tool formatting your SQL according to a number of rules. I was happy to find that my way of writing SQL was supported:
SELECT a, b, c AS d FROM x, y, z AS w WHERE a = 2 AND b IN (3,4,7)
And another example:
SELECT obj.run, obj.camcol, STR(obj.field,3) AS field, STR(obj.rowc,6,1) AS rowc, STR(obj.colc,6,1) AS colc, STR(dbo.FOBJ(obj.objid),4) AS id, STR(obj.psfmag_g - 0 * obj.extinction_g,6,3) AS g, STR(obj.psfmag_r - 0 * obj.extinction_r,6,3) AS r, STR(obj.psfmag_i - 0 * obj.extinction_i,6,3) AS i, STR(obj.psfmag_z - 0 * obj.extinction_z,6,3) AS z, STR(60 * distance,3,1) AS d, dbo.FFIELD(neighborobjid) AS nfield, STR(dbo.FOBJ(neighborobjid),4) AS nid, 'new' AS 'new' FROM (SELECT obj.objid, run, camcol, field, rowc, colc, psfmag_u, extinction_u, psfmag_g, extinction_g, psfmag_r, extinction_r, psfmag_i, extinction_i, psfmag_z, extinction_z, nn.neighborobjid, nn.distance FROM photoobj AS obj JOIN neighbors AS nn ON obj.objid = nn.objid WHERE 60 * nn.distance BETWEEN 0 AND 15 AND nn.mode = 1 AND nn.neighbormode = 1 AND run = 756 AND camcol = 5 AND obj.TYPE = 6 AND (obj.flags & 0x40006) = 0 AND nchild = 0 AND obj.psfmag_i < 20 AND (g - r BETWEEN 0.3 AND 1.1 AND r - i BETWEEN -0.1 AND 0.6)) AS obj JOIN photoobj AS nobj ON nobj.objid = obj.neighborobjid WHERE nobj.run = obj.run AND (ABS(obj.psfmag_g - nobj.psfmag_g) < 0.5 OR ABS(obj.psfmag_r - nobj.psfmag_r) < 0.5 OR ABS(obj.psfmag_i - nobj.psfmag_i) < 0.5)ORDER BY obj.run, obj.camcol, obj.field
I don't know what's worse; making crosswords with only SQL related questions (requires free registration to access) or actually trying to solve the same. This is one of many thing that currently puzzles me. One other thing that also scares me is that I get annoyed when I cannot solve these crosswords right away...
When looking at BDD and TDD examples it is very common to see the use of mock objects in the code. This however strikes me as a little bit strange since I think you should use stubs and not mocks when working with BDD/TDD. A mock is basically a stub with the added knowledge that a mock object knows how it is expected to be used. In my opinion this fact disturbs the focus when applying BDD/TDD. Additionally I think maintainability is decreased since the tests will now have a dependency on implementation internals and you risk having to change your test not because the API has changed but how things are done internally.
Let me explain what I mean with an example. Consider a data object used to handle transactions and the ability to read and modify the amount money on a given bank account. Now assume this data object is used as a parameter to a transfer method that is used to transfer funds between two accounts. One way to implement the transfer method could be:
From a maintainability point of view I think mocking the data object will be risky since the mock will verify that the correct number of calls are made in the correct order. It wouldn't surprise me if we some day saw a new transfer implementation looking something like this:
The example may seem a little far-fetched but still I think it points toward a maintainability risk involved when using a mock. But OK, let's assume that maintainability will not be a problem. We're still shifting focus from what is important I think. As soon as a mock is involved when I write my test/scenario I do not only have to think about the behavior I expect. I must also think about how my mock will be used since that may or may not affect my test code. Using stubs instead of mocks will reduce that focus shift since stubs are just doing what they're told without regard of context.
Sure one might argue that using stubs will also involve having to think about how the stub is used. That is true but without the risk of having order or number of calls to the stub mess up your test/scenario setup. And the less time you spend on thinking about setup and the more you spend on defining behavior, the better I think. And thinking about behavior of internals and/or dependent objects should just be kept to an absolute minimum if you ask me.
Yesterday I attended a presentation at Tobii on how they've implemented Scrum in one of their development teams. The presentation was started by Henrik Kniberg who gave a short introduction to Scrum. I do not envy his task since a quick poll showed that more than half of the audience was practicing Scrum in their current project. One thing that always amazes me at these kind of presentations are the two or three persons attending who think that Scrum is a silver bullet solution to all problems and who ask all kinds of questions related to their current situation trying to figure out what they have to do in order to make their Scrum implementation more successful. What they don't seem to get is that Scrum is not the answer to your problems - it just helps you see your problems. You still have to solve the problems yourself!
But back to Tobii. We got a great demo on what eye tracking software can be used for,including playing FPS games. And I must say it was extra interesting for me to see what the team was really developing since I was the person brought in to coach them when they wanted to start using Scrum. I attended daily scrums, sprint demos and retrospectives but I never got a chance to see and understand what they really accomplished.
So how did they implement Scrum? I would say they pretty much implemented vanilla scrum from out of the box I would say. But this is usually not enough to successfully implement Scrum I would say. In their case I think the following things were the keys to success:
So what can you learn from this? Well, doing great stuff is always easy when you have great people to work with. The team I worked with at Tobii had all the best prerequisites for success and that is one thing you either have or you haven't. But what you can do is to use a coach. Having the ability to discuss different matters with someone outside of your regular workmates as well as having somebody that easily can say those things everybody want to say but are afraid to say can in some cases be what makes or break your implementation of Scrum.
Previously I've written about where to start when applying agile to your project. But not all people are happy with that since they want to read a book. Fair enough - I also started out reading books when agile cached my interest. So people I know tend to ask me what books I recommend to someone who wants o learn more. Typically they ask for a book on Scrum but that is not really what they want. They want a book to help them work better in their project.So this is my prioritized list on books to read when you want to learn more and implement agile into your project successfully. It is prioritized so if you only read one book, read the first one and then add more reading as you have time.
Of cause there are more books on certain topics like TDD but that is not the typical question I get. So I'll leave such books for a future list. Maybe.
In my career I've worked with stored procedures in a way I think many people never do. For example I've worked on projects where both the data access and the business logic have been placed in the database in the form of stored procedures. Not quite your standard three-tier solution but it works quite well when the people with all the business knowledge also knows a lot about databases and SQL but less about anything else. Obviously this involves a lot of data being passed around between stored procedures.
This means that I've seen a few different ways to pass data around and I'm sad I didn't find this page earlier. Sommerskog's description of the pros and cons with different approaches would definitely have saved be some time. Over the years I've tried output parameters, cursors, tables, user defined functions and the table data type. And as usual the latest technology is not the best for all situations but may simplify things that was cumbersome to accomplish before.
And some times the simplest solution is the most brilliant. A common problem I've faced is that I have one SP (stored procedure) returning some data as a select statement. Later on I want to reuse that SP in several other SPs. Previously I've been using functions or temporary tables to do this which both have their disadvantages, rewriting the original SP being one. But with the insert-exec pattern I can reuse the SP right away. I'm embarrassed I didn't think of that before. Let's say it is so obvious you don't think about it. In the same way you forget to look for your glasses on your nose. It's no silver bullet and it wouldn't have solved all my problems but it is yet another tool to use.
So if you're working with databases you should definitely take a closer look at what Sommerskog is writing because knowing things like that will definitely make your life easier. And there is no point in learning it the hard way by your self.