0

I have run EclEmma for coverage on my JUnit Test Cases and have reached up to 100% on some. However, on the ones that are 82% or 95% covered, there is a message next to my code that says "1 of 2 branches missed" and I can't seem to solve this issue.

After looking over my classes, I noticed that this message only appears next to my if-statements, and that is what's keeping my tests from being 100% covered.

I guess I'm asking if anyone knows how to test an if-statement in JUnit, so that neither branch is missed.

This is the code I'm trying to test:

private double height;
    public void setHeight(double height){
        if(height <=0){
            this.height = 0;
        }
        else{
            this.height = height;
        }
    }//method close

( I am using JUnit 4 )

GhostCat
  • 127,190
  • 21
  • 146
  • 218
user1975
  • 11
  • 1
  • 3
  • 3
    Call `setHeight` with a negative number, a positive number, and maybe with 0. Really, what exactly are you asking? – Seelenvirtuose Mar 07 '17 at 07:28
  • So, test with a height that is <= 0, and test with a height > 0. That will cover both branches. – JB Nizet Mar 07 '17 at 07:28
  • btw: comparing doubles with == is not safe in Java (and other languages). http://stackoverflow.com/questions/25160375/comparing-double-values-for-equality-in-java – Rainer Mar 07 '17 at 07:32
  • 2
    Is mandatory for you to have a 100% coverage? I think it is never necessary to have a plenty coverage of the code, just a reasonable percentage would be good. Cover all branches and line of code is not a guarantee your code is correct. maybe you could cover more real cases instead. – Mario Santini Mar 07 '17 at 07:32
  • Test behaviour, not code: write the test to show that `this.height` is always at least zero after calling the method, even if a negative parameter is passed. The implementation (and thus coverage) of that is somewhat irrelevant. – Andy Turner Mar 07 '17 at 07:41
  • Also, consider that throwing an `IllegalArgumentException` might be more appropriate in the case of a negative argument. – Andy Turner Mar 07 '17 at 07:43
  • 1
    @Rainer Sorry, I can't hear that nonsense any more. Comparing doubles with == is sometimes not safe, sometimes it is. Here, using <= definitely is ok (although I'd vote for throwing an exception for a negative argument). Of course one should know when it is safe and when it isn't. But this general advice IMHO does more harm than good. – Axel Mar 07 '17 at 07:46
  • Thanks for all of your help. I was able to run the test and get 100% coverage. – user1975 Mar 07 '17 at 07:50
  • I am glad you found my input helpful; please consider accepting the most helpful answer at some point. – GhostCat Mar 07 '17 at 07:54
  • @Axel I would say that depends on your application scenario. Comparing double in Java with == (which includes of course <= and >=) is NOT safe and if life is at risk because of your code you should not do it. If a fail in your code leads to a loss of a few $ for an only shop - then sure - go ahead using it. – Rainer Mar 14 '17 at 08:22
  • @Rainer So how should the test be written in this example? if `(!(height>0))`? Would that make you feel better? Or would you use an epsilon, like `if (height>-epsilon)`? If yes, I'd feel better not having my life depend on your code... – Axel Mar 14 '17 at 11:07
  • @Axel why so rude? Calling my comment nonsense? It just mentioned that there are cases where == isn´t sufficient (as mentioned in the linked SO-question). Comparing with 0 literal should be fine though. – Rainer Mar 14 '17 at 13:36
  • @Rainer Sorry, I think I was overreacting. Maybe I have a little bit too much stress these days. Also I am a bit allergic to "never use == for double" comments because it is the correct thing to do in many cases (but you better know when it is not). The other one is "always use BigDecimal for money" (in 15 years I have never seen BigDecimal being actually used in practice - and I work in the financial sector). I have to admit that I am sometimes not really comfortable with that though. – Axel Mar 14 '17 at 15:59
  • @Axel that´s right. btw. One of Java 9 Key-features is a "Money-API" ;-) I never considered BigDecimal like you, but maybe the new API is worth a look for future applications. https://www.infoq.com/articles/JSR-354-Java-Money-Currency-API – Rainer Mar 15 '17 at 16:29

2 Answers2

4

Simple:

you want to have one distinct test case per path within your method under test; like:

  • testSetHeightWithNegativeValue()
  • testSetHeightWithZeroValue()
  • testSetHeightWithPositiveValue

Each of them gives specific input to your method under test and checks for the expected output.

Where the real take away here is: consider thinking about your code. You should not need a coverage tool to figure that you need more tests for your method. Instead: you look at your method, and think what it is doing; and then you write testcases.

Coverage is fine to tell you that you did the right thing; but "doing the right thing" is what you should strive to do by yourself; and not to meet some numbers.

And, as the comments point out: consider using the TDD approach: when you write your tests before you create the "matching" piece of production code, then you make that "thinking" part an essential element of your working procedure.

GhostCat
  • 127,190
  • 21
  • 146
  • 218
  • Well, considering TDD you should even write the testcase BEFORE writing your method (http://stackoverflow.com/questions/804569/why-should-i-use-test-driven-development) – Rainer Mar 07 '17 at 07:34
  • Ran the test again and got 100% coverage. Thanks for your help! – user1975 Mar 07 '17 at 07:46
  • @Rainer I thought about TDD, but forgot to mention that; just updated my answer. – GhostCat Mar 07 '17 at 07:54
1

Your code

public void setHeight(double height){
    if(height <=0){
        this.height = 0;
    }
    else{
        this.height = height;
    }
}

has two possible branches:

height <= 0

public void setHeight(double height){
     this.height = 0;
}

height > 0

public void setHeight(double height){
    this.height = height;
}

So in if statement, you can go to one statement or another in else. You have to create two unit tests to cover all possible ways - one for parameter passed height > 0 and second for height <= 0

ByeBye
  • 5,685
  • 3
  • 24
  • 54