0

I am trying to cover all blocks in this piece of code. All lines appear to be covered, says code-coverage. But two blocks stay uncovered and I can't figure out how.

This is the code I am writing unittests for:

public TRange Intersect(TRange range)
{
    Validator.IsNotNull(range, "range");
    if (!HasOverlap(range))
        return null;
    return Calculator.FromStartStop(
        Tools.Max(Start, range.Start) ?? Start ?? range.Start, 
        Tools.Min(Stop, range.Stop) ?? Stop ?? range.Stop);
}

To explain: this code returns the intersect of two ranges: Say if you had an IntegerRange (hereafter: IntRange) of [10..20] and one of [15..25]; the result of the intersect would be [15..20]. As indicated above, it takes the max-value of the start, and the min-value of the stop.

The validator checks for an null-range. The HasOverlap checks if both ranges are "inside" eachother: [10..20] and [15..25] are, but [10..20] and [25..30] are not.

My unittests so far covered 36 of the 38 blocks.

[TestMethod]
public void IntersectTest()
{
    IntRange intRange510 = IntRange.FromStartStop(5, 10);
    IntRange intRange520 = IntRange.FromStartStop(5, 20);
    IntRange intRange4050 = IntRange.FromStartStop(40, 50);
    IntRange intRange1020 = IntRange.FromStartStop(10, 20);
    IntRange intRange1530 = IntRange.FromStartStop(15, 30);
    IntRange intRange2030 = IntRange.FromStartStop(20, 30);
    IntRange intRangenull5 = IntRange.FromStartStop(null, 5);
    IntRange intRangenull10 = IntRange.FromStartStop(null, 10);
    IntRange intRangenull20 = IntRange.FromStartStop(null, 20);
    IntRange intRange5null = IntRange.FromStartStop(5, null);
    IntRange intRange10null = IntRange.FromStartStop(10, null);
    IntRange intRange20null = IntRange.FromStartStop(20, null);
    IntRange intRangenullnull = IntRange.FromStartStop(null, null);

    //4x x/null
    Assert.AreEqual(intRangenullnull, intRangenullnull.Intersect(intRangenullnull));
    Assert.AreEqual(IntRange.FromStartStop(15,20), intRange1020.Intersect(intRange1530));

    // 3x nulltest
    Assert.AreEqual(intRange10null, intRange10null.Intersect(intRangenullnull));
    Assert.AreEqual(intRangenull10, intRangenull10.Intersect(intRangenullnull));
    Assert.AreEqual(intRange10null, intRangenullnull.Intersect(intRange10null));
    Assert.AreEqual(intRangenull10, intRangenullnull.Intersect(intRangenull10));

    // 2x nulltest
    Assert.AreEqual(intRange1020, intRangenullnull.Intersect(intRange1020));
    Assert.AreEqual(intRangenull10, intRangenull10.Intersect(intRangenull20));
    Assert.AreEqual(intRangenull10, intRangenull20.Intersect(intRangenull10));
    Assert.AreEqual(intRange510, intRangenull10.Intersect(intRange5null));
    Assert.AreEqual(intRange510, intRange5null.Intersect(intRangenull10));
    Assert.AreEqual(intRange10null, intRange10null.Intersect(intRange5null));
    Assert.AreEqual(intRange20null, intRange10null.Intersect(intRange20null));
    Assert.AreEqual(intRange1020, intRange1020.Intersect(intRangenullnull));

    // 1x nulltest
    Assert.AreEqual(intRange510, intRangenull10.Intersect(intRange510));
    Assert.AreEqual(intRange510, intRangenull10.Intersect(intRange520));
    Assert.AreEqual(intRange1020, intRange10null.Intersect(intRange1020));
    Assert.AreEqual(intRange1020, intRange10null.Intersect(intRange520));
    Assert.AreEqual(intRange510, intRange510.Intersect(intRangenull20));
    Assert.AreEqual(intRange510, intRange520.Intersect(intRangenull10));
    Assert.AreEqual(intRange2030, intRange1530.Intersect(intRange20null));
    Assert.AreEqual(intRange1530, intRange1530.Intersect(intRange5null));

    // No overlap
    Assert.IsNull(intRange510.Intersect(intRange4050));
}

[TestMethod]
[ExpectedException(typeof(ValidationException))]
public void EmptyIntersectTest()
{
    IntRange intRange = null;
    _Range10To20.Intersect(intRange);
} 

I also checked the de-compiled (and converted) code but could not find what I was missing:

public TRange Intersect(TRange range)
{
    Validator.IsNotNull(range, "range");
    TRange result;
    if (!this.HasOverlap(range))
    {
        result = default(TRange);
    }
    else
    {
        RangeCalculatorBase<TRange, TStartStop, TLength> arg_ED_0 = Range<TRange, TStartStop, TLength>.Calculator;
        TStartStop? tStartStop = Tools.Max<TStartStop?>(this.Start, range.Start);
        TStartStop? arg_ED_1;
        if (!tStartStop.HasValue)
        {
            TStartStop? tStartStop2 = this.Start;
            arg_ED_1 = (tStartStop2.HasValue ? new TStartStop?(tStartStop2.GetValueOrDefault()) : range.Start);
        }
        else
        {
            arg_ED_1 = new TStartStop?(tStartStop.GetValueOrDefault());
        }
        tStartStop = Tools.Min<TStartStop?>(this.Stop, range.Stop);
        TStartStop? arg_ED_2;
        if (!tStartStop.HasValue)
        {
            TStartStop? tStartStop2 = this.Stop;
            arg_ED_2 = (tStartStop2.HasValue ? new TStartStop?(tStartStop2.GetValueOrDefault()) : range.Stop);
        }
        else
        {
            arg_ED_2 = new TStartStop?(tStartStop.GetValueOrDefault());
        }
        result = arg_ED_0.FromStartStop(arg_ED_1, arg_ED_2);
    }
    return result;
}

What am I not testing here?

Addition: IntRange inherits from TRange but does not add anything new.

Matthijs
  • 3,162
  • 4
  • 25
  • 46
  • Can you clarify what you mean by "covered 36 of the 38 blocks"? Also, what blocks are (allegedly) not covered? – Lilshieste May 02 '14 at 17:56
  • I am not sure if you are familiar with the Code Coverage mechanism in Visual Studio? This tells you how many blocks and lines are uncovered, along with some other data. I can not see which blocks are uncovered. All lines are covered, but apparently some of the compiled code does not get hit. And I am trying to figure out how to cover that code entirely. – Matthijs May 04 '14 at 13:56
  • Sorry, I only have a passing familiarity with the VS code coverage feature. Do you have any iterator blocks in your code? I do know that iterator blocks are notorious for tripping up code coverage tools, on account of their compiler-generated code. http://stackoverflow.com/questions/11918858/weird-test-coverage-results-for-iterator-block-why-are-these-statements-not-exe – Lilshieste May 05 '14 at 12:48
  • I am familiar with this yes. But as you can read above, my code does not contain any iterator blocks. My guess is that it has something to do with the ternary-operatorexpressions; I am thinking not all combinations are used in my unittests, but which I am unable to discover. – Matthijs May 05 '14 at 13:12

0 Answers0