How can I get 100% test coverage in a Perl module that uses DBI?
code-coverage, dbi, perl, testing
Solution
Also, don't get too hung up on 100% test coverage. The goal is to fully test your application, not get perfect scores in Devel::Cover. See Ovid's posts on the subject:
- More on 100% Test Coverage
- 100% Test Coverage?
In your case, it looks like you don't cover all the branches, so you don't get perfect scores. You need to tests that exercise both sides of that `||`. You're getting 33% percent coverage because you only handle one-third of the cases for that line. The HTML report from Devel::Cover shows you the truth table and which cases you are missing.
The truth table shows you the possible states that you have to cover for the branching. A `1` shows you a condition which is true, `0` shows you a condition that is false, and `X` shows you a condition you won't reach. You have to test all combinations that can execute. Since the `||` is a short-circuit operator, you don't have to test conditions once one of them passes:
0 || 1 connect to database fails and croak succeeds
0 || 0 connect to database fails and croak fails (unlikely)
1 || X connect to database succeeds, so short circuit
This is a bit unrelated to your particular problem, but I find it comes up often in these problems. Although Effective Perl Programming is a month of so away from hitting the shelves, Josh McAdams spent quite a bit of time talking about dependency injection in Perl. If you're having a tough time testing your code, you usually have a design problem. If you're internally generating database objects in subroutines, for instance, you are painting yourself into a corner. That's why it might be hard to test. This may not be the problem in your case, but it's something to think about.
Problem
I am a bit new to the Devel::Cover module, but have found it very useful in making sure I am not missing tests. A problem I am running into is understanding the report from Devel::Cover. I've looked at the documentation, but can't figure out what I need to test to get 100% coverage. Edit - I should make it clear that I am not saying I need 100% coverage, because as multiple people point out, 100% coverage is a loose term, does not mean that my code is bug free, and may not always be completely necessary. Since I am new at Devel::Cover, I am interested to know why my code is not 100% coverage, in case I am missing some important tests. Here is the output from the cover report: ``` line err stmt bran cond sub pod time code ... 36 sub connect_database { 37 3 3 1 1126 my $self = shift; 38 3 100 24 if ( !$self->{dsn} ) { 39 1 7 croak 'dsn not supplied - cannot connect'; 40 } 41 *** 2 33 21 $self->{dbh} = DBI->connect( $self->{dsn}, q{}, q{} ) 42 || croak "$DBI::errstr"; 43 1 11 return $self; 44 } ... line err % l !l&&r !l&&!r expr ----- --- ------ ------ ------ ------ ---- 41 *** 33 1 0 0 'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr") ``` And here is and example of my code that tests this specific line: ``` my $database = MyModule::Database->new( { dsn => 'Invalid DSN' }); throws_ok( sub { $database->connect_database() }, qr/Can't connect to data source/, 'Test connection exception (invalid dsn)' ); ``` This test passes - the connect does throw an error and fulfills my "throws_ok" test. I do have some tests that test for a successful connection, which is why I think I have 33% coverage, but if I'm reading it correctly, cover thinks I am not testing the "|| croak" part of the statement. I thought I was, with the "throws_ok" test, but obviously I am missing something. Does anyone have advice on how I can test my DBI->connect line successfully? Thanks! Edit: brian tipped me off to the HTML report and the truth table that explains why line #41 is not passing. The only problem is that I can't figure out what it is telling me. I guess the real core of my question is why is this specific line not passing coverage. Here is the truth table: ``` LINE # % # coverage # condition 41 # 33 # A | B | dec # 'DBI'->connect($$self{'dsn'}, '', '') || croak("$DBI::errstr") # # 0 | 0 | 0 # # # 0 | 1 | 1 # # # 1 | X | 1 # (THIS LINE IS Green - the rest are red) ``` If anyone could help explain this truth table, I'd appreciate it. It has also been mentioned that to pass the coverage I need to have a mock database object, but I don't quite see how anything in the coverage results that would clue me in to this. Thanks again!