Exhaustive unit tests

Chris via Digitalmars-d digitalmars-d at puremagic.com
Thu May 28 02:46:17 PDT 2015

I'm referring to this bug/enhancement request:


I checked the unit test(s) for it (see below), and found that 
they only check for the positive case, i.e. that a substitution 
takes place, not for the case that no substitution takes place. 
The bug referred to above would have been spotted by testing for 
a mismatch.

Exactly this kind of optimistic unit testing has happened to me 
too. The problem is the "gold standard phenomenon". If you test 
your program against a gold standard, you tend to focus only on 
this standard and think that everything is all right, once you 
meet all the criteria of the standard. However, you forget to 
test for deviating, non-standard behavior. I wonder how much of 
this is still in Phobos. I'm sure someone has opened a ticket / 
PR or something on this, haven't they?

The problem here is that you probably wouldn't have spotted the 
flaw in the unit test by running "-unittest -cov". For 
replaceFirst yes (although not obvious)

        |public R replaceFirst(R, C, RegEx)(R input, RegEx re, 
const(C)[] format)
        |    if(isSomeString!R && is(C : dchar) && 
isRegexFor!(RegEx, R))
      36|    return replaceFirstWith!((m, sink) => 
replaceFmt(format, m, sink))(input, re);

        |//  a general skeleton of replaceFirst
        |private R replaceFirstWith(alias output, R, RegEx)(R 
input, RegEx re)
        |    if(isSomeString!R && isRegexFor!(RegEx, R))
      25|    auto data = matchFirst(input, re);
      25|    if(data.empty)
0000000|        return input;  // <== Not tested for
      25|    auto app = appender!(R)();
      25|    replaceCapturesInto!output(app, input, data);
      25|    return app.data;

but not for replaceFirstInto

public @trusted void replaceFirstInto(Sink, R, C, RegEx)
        |        (ref Sink sink, R input, RegEx re, const(C)[] 
        |    if(isOutputRange!(Sink, dchar) && isSomeString!R
        |        && is(C : dchar) && isRegexFor!(RegEx, R))
        |    {
      39|    replaceCapturesInto!((m, sink) => replaceFmt(format, 
m, sink))
        |        (sink, input, matchFirst(input, re));
        |    }
        |public @trusted void replaceFirstInto(alias fun, Sink, R, 
        |    (Sink sink, R input, RegEx re)
        |    if(isOutputRange!(Sink, dchar) && isSomeString!R && 
isRegexFor!(RegEx, R))
       1|    replaceCapturesInto!fun(sink, input, 
matchFirst(input, re));

        |// the lowest level - just stuff replacements into the 
        |private @trusted void replaceCapturesInto(alias output, 
Sink, R, T)
        |        (ref Sink sink, R input, T captures)
        |    if(isOutputRange!(Sink, dchar) && isSomeString!R)
      39|    sink.put(captures.pre);
        |    // a hack to get around bogus errors, should be 
simply output(captures, sink)
        |    // "is a nested function and cannot be accessed from"
        |    static if(isReplaceFunctor!(output, R))
       1|        sink.put(output(captures)); //"mutator" type of 
        |    else
      38|        output(captures, sink); //"output" type of 
      39|    sink.put(captures.post);

package.d is 88% covered

Unit test in std/regex/package.d


See also:

More information about the Digitalmars-d mailing list