On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
More and more, D code is written as a component that takes a type parameters that are ranges. Unit testing becomes inconvenient, as types must be mocked up to call them. Using an array of data often is inadequate, because the component may have specializations for an array, or specifies a range that is a subset of what an array provides.

For example, here's a test range I wrote once for a unittest:

  struct Adapter
  {
      this(ubyte[] r) { this.r = r; }
      @property bool empty() { return r.length == 0; }
      @property ubyte front() { return r[0]; }
      void popFront() { r = r[1 .. $]; }
      @property size_t length() { return r.length; }

    private:
      ubyte[] r;
  }

I propose a std.test.ranges package, which contains templates defining each of the range types (InputRange, BiDirectionalRange, etc.). Each accepts an argument which is a static array of T, and then implements exactly the range interface indicated by its name, nothing more. The range will also have asserts to guarantee they are used correctly, i.e. front() cannot be called before empty() returns false.

Great idea. It might even be better to split the two concerns: Mock ranges taking the static array as data and testing wrappers that enforce correct usage of wrapped ranges.

So that I can

TokenRange lex() { ... } // returns a range of token

// check that the TokenRange is a valid forward range
testIsForwardRange!TokenRange

// parser
auto parse(TR)(TR r) { ... }

// normal use
auto result = parse(lex());
// testing that parse uses the TR correctly
auto result = parse(assertingForwardRange(lex()));

This way it's easier to craft input for testing the correctness of parse.

Reply via email to