Jump to page: 1 2 3
Thread overview
Testing package proposed for Phobos
Feb 09, 2015
Walter Bright
Feb 09, 2015
Jakob Ovrum
Feb 09, 2015
Walter Bright
Feb 09, 2015
H. S. Teoh
Feb 09, 2015
Walter Bright
Feb 09, 2015
John Colvin
Feb 10, 2015
Walter Bright
Feb 10, 2015
Jonathan M Davis
Feb 09, 2015
Craig Dillabaugh
Feb 09, 2015
Russel Winder
Feb 09, 2015
Atila Neves
Feb 09, 2015
Walter Bright
Feb 09, 2015
H. S. Teoh
Feb 09, 2015
CraigDillabaugh
Feb 09, 2015
ketmar
Feb 10, 2015
Brad Anderson
Feb 10, 2015
H. S. Teoh
Feb 10, 2015
ketmar
Feb 09, 2015
Tobias Pankrath
Feb 10, 2015
Walter Bright
Feb 10, 2015
Walter Bright
Feb 11, 2015
Walter Bright
Feb 11, 2015
Walter Bright
Feb 11, 2015
FG
February 09, 2015
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.

By default, those mock range templates will be @safe. They can be configured to be @system.

Each range type will also have a corresponding testXXXRange!R(R r) function, that tests the interface to range R to ensure that it follows the protocol indicated by its name (there was some confusion a while back about exactly what the protocol entailed, having a standard test function for it will help user defined ranges be protocol correct).

Anyone interested in taking up this flag?
February 09, 2015
On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
> Anyone interested in taking up this flag?

Is this idea different from the one in std.internal.test.dummyrange?
February 09, 2015
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.
>
> By default, those mock range templates will be @safe. They can be configured to be @system.
>
> Each range type will also have a corresponding testXXXRange!R(R r) function, that tests the interface to range R to ensure that it follows the protocol indicated by its name (there was some confusion a while back about exactly what the protocol entailed, having a standard test function for it will help user defined ranges be protocol correct).
>
> Anyone interested in taking up this flag?

Google Summer of Code project?  Are you interested in mentoring?

(Sorry, I have a bit of a one-track mind)
February 09, 2015
I.e. by providing standard mockups for components, and standard tests for component protocols, we can significantly improve the unit testing and standard conformance of user designed components.
February 09, 2015
On 2/8/2015 5:52 PM, Jakob Ovrum wrote:
> On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
>> Anyone interested in taking up this flag?
>
> Is this idea different from the one in std.internal.test.dummyrange?

I wasn't aware of the existence of that. Will check it out.
February 09, 2015
On Sun, Feb 08, 2015 at 06:08:31PM -0800, Walter Bright via Digitalmars-d wrote:
> On 2/8/2015 5:52 PM, Jakob Ovrum wrote:
> >On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
> >>Anyone interested in taking up this flag?
> >
> >Is this idea different from the one in std.internal.test.dummyrange?
> 
> I wasn't aware of the existence of that. Will check it out.

And while we're at it, we might want to look at consolidating some of the other unittest-specific stuff that's sprinkled throughout Phobos modules, such as in std.algorithm.package (search for "rndstuff" in package.d).


T

-- 
Why waste time reinventing the wheel, when you could be reinventing the engine? -- Damian Conway
February 09, 2015
On 2/8/2015 6:08 PM, Walter Bright wrote:
> On 2/8/2015 5:52 PM, Jakob Ovrum wrote:
>> On Monday, 9 February 2015 at 01:41:33 UTC, Walter Bright wrote:
>>> Anyone interested in taking up this flag?
>>
>> Is this idea different from the one in std.internal.test.dummyrange?
>
> I wasn't aware of the existence of that. Will check it out.

Cursory review:

1. Yes, it's what I was asking for, at least in part.

2. Being in std.internal.test implies it is not for general usage. It needs to be for general usage.

3. It's used here:

grep -r std.internal.test *.d
algorithm\comparison.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\iteration.d:    import std.internal.test.dummyrange;
algorithm\mutation.d:    import std.internal.test.dummyrange;
algorithm\mutation.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
algorithm\searching.d:    import std.internal.test.dummyrange;
internal\test\dummyrange.d:module std.internal.test.dummyrange;
range\constraints.d:    import std.internal.test.dummyrange;
range\interfaces.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\package.d:    import std.internal.test.dummyrange;
range\primitives.d:    import std.internal.test.dummyrange;

I'd like to see it used much more pervasively in Phobos - essentially with every range that is defined, and every component that takes a range as a parameter, unless there's a good reason not to on a case-by-case basis.

4. It's only for uint data. This should be parameterized.

5. It's terribly underdocumented. I have no idea what ReturnBy, Length, or RangeType are without reading the implementation code.

6. It does not contain any protocol verification - for example, front() does not check that empty() was called beforehand.

7. There's not a single unittest in it.

8. I don't see any connection between DummyRange and ReferenceInputRange.

9. There are no test functions which accept an input range and test that the protocol at least exists and does not crash.

10. No @system types.

11. No output ranges.

I.e. it's a good starting point, but there's a lot more that can be done.
February 09, 2015
On Sun, Feb 08, 2015 at 06:06:59PM -0800, Walter Bright via Digitalmars-d wrote:
> I.e. by providing standard mockups for components, and standard tests for component protocols, we can significantly improve the unit testing and standard conformance of user designed components.

Yes, I've suggested this a long time ago but it seemed to have fallen by the wayside. It would be good to provide standard testing stuff for:

- Non-forward input ranges.
- Forward but non-bidirectional ranges.
- Bidirectional but not random access ranges.
- Infinite ranges vs. finite ranges.
- Ranges with reference semantics vs. value semantics.
- Array-like ranges that are not arrays.

Ideally, every range-based function in Phobos should be tested with each of these variations, to ensure correct semantics under all representative use cases.


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain
February 09, 2015
On Mon, 2015-02-09 at 01:54 +0000, Craig Dillabaugh via Digitalmars-d
wrote:
[…]
> 
> Google Summer of Code project?  Are you interested in mentoring?
> 
> (Sorry, I have a bit of a one-track mind)

A point came up at the London D Users meeting:

Having unittest integrated into module structure and compiler is fine for small unit tests, but what is the D support for integration tests, end-to-end tests, etc. What is the equivalent in D of Catch, TestNG, Spock, Cucumber,…

If there is one, I should have known it. If there isn't then GSoC 2015 would be a good place to get a start with Catch and Spock being the things to use for inspiration.

I'd be happy to mentor.


-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


February 09, 2015
> A point came up at the London D Users meeting:
>
> Having unittest integrated into module structure and compiler is fine
> for small unit tests, but what is the D support for integration tests,
> end-to-end tests, etc. What is the equivalent in D of Catch, TestNG,
> Spock, Cucumber,…


https://github.com/atilaneves/unit-threaded
https://github.com/atilaneves/unencumbered

Atila
« First   ‹ Prev
1 2 3