← Back to team overview

nunit-core team mailing list archive

[Bug 901212] [NEW] Feature request: Generic constraint model

 

Public bug reported:

For NUnit v3, a fully generic constraint system (i.e., the Constraint
and ConstraintExpression classes having a generic type parameter T)
would be desirable in order to be able to leverage types known at
compile time when writing constraints. Constraint methods such as Equal
and GreaterTo could use that type parameter in their signature, so
invalid comparisons would be detected at compile time. Constraints such
as Property could provide support for naming symbols using expressions
(Expression<Func<T, TR>>). For collection constraints, a TElement
generic parameter knowing the element type of the collection should also
be added.

The classic constraint builders Is and Has would instantiate the T (and
TElement) with System.Object, so that "Assert.That (myValue, Is.EqualTo
(10))" would cause an EqualConstraint<object> to be passed to
Assert.That and "Assert.That (myValue, Has.Member (10))" would cause a
CollectionContainsConstraint<object> (derived from Constraint<T> with T
being IEnumerable<object> in this case) to be passed to Assert.That.

Is.TypeOf<T>, Is.AssignableTo<T>, and Is.InstanceOf<T> would return
their respective constraints parameterized with the given T, so that
"Assert.That (myValue, Is.TypeOf<MyClass>().With.Property (v =>
v.P).EqualTo (42))" would work.

For full type inference support, a new Assert.That syntax could be provided that binds the T to the actual type of the value passed to the Assert method:
public static void That<T> (T actualValue, Func<ResolveConstraintBuilder<T>, IResolveConstraint<T>> constraintDelegate)
and
public static void That<TElement> (IEnumerable<TElement> actualValue, Func<ResolveCollectionConstraintBuilder<TElement>, IResolveConstraint<IEnumerable<TElement>>> constraintDelegate).

This would allow code such as the following to be written in a typesafe way without needing to repeat the type:
Assert.That (myVariable, v => v.EqualTo (42));
Assert.That (myCollection, c => c.EquivalentTo (new[] { 1, 2, 3 }));
Assert.That (myCollection, c => c.Member (3));

** Affects: nunitv2
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of NUnit
Developers, which is subscribed to NUnit V2.
https://bugs.launchpad.net/bugs/901212

Title:
  Feature request: Generic constraint model

Status in NUnit V2 Test Framework:
  New

Bug description:
  For NUnit v3, a fully generic constraint system (i.e., the Constraint
  and ConstraintExpression classes having a generic type parameter T)
  would be desirable in order to be able to leverage types known at
  compile time when writing constraints. Constraint methods such as
  Equal and GreaterTo could use that type parameter in their signature,
  so invalid comparisons would be detected at compile time. Constraints
  such as Property could provide support for naming symbols using
  expressions (Expression<Func<T, TR>>). For collection constraints, a
  TElement generic parameter knowing the element type of the collection
  should also be added.

  The classic constraint builders Is and Has would instantiate the T
  (and TElement) with System.Object, so that "Assert.That (myValue,
  Is.EqualTo (10))" would cause an EqualConstraint<object> to be passed
  to Assert.That and "Assert.That (myValue, Has.Member (10))" would
  cause a CollectionContainsConstraint<object> (derived from
  Constraint<T> with T being IEnumerable<object> in this case) to be
  passed to Assert.That.

  Is.TypeOf<T>, Is.AssignableTo<T>, and Is.InstanceOf<T> would return
  their respective constraints parameterized with the given T, so that
  "Assert.That (myValue, Is.TypeOf<MyClass>().With.Property (v =>
  v.P).EqualTo (42))" would work.

  For full type inference support, a new Assert.That syntax could be provided that binds the T to the actual type of the value passed to the Assert method:
  public static void That<T> (T actualValue, Func<ResolveConstraintBuilder<T>, IResolveConstraint<T>> constraintDelegate)
  and
  public static void That<TElement> (IEnumerable<TElement> actualValue, Func<ResolveCollectionConstraintBuilder<TElement>, IResolveConstraint<IEnumerable<TElement>>> constraintDelegate).

  This would allow code such as the following to be written in a typesafe way without needing to repeat the type:
  Assert.That (myVariable, v => v.EqualTo (42));
  Assert.That (myCollection, c => c.EquivalentTo (new[] { 1, 2, 3 }));
  Assert.That (myCollection, c => c.Member (3));

To manage notifications about this bug go to:
https://bugs.launchpad.net/nunitv2/+bug/901212/+subscriptions


Follow ups

References