Re: Writing New Constraints for NUnit

"Charlie Poole" <[email protected]> Mon, 8 Sep 2008 02:16:30 -0700
Newsgroups gmane.comp.windows.dotnet.nunit.user
Message-ID <002e01c91193$954dac10$6401a8c0@ferrari>
This is a multi-part message in MIME format.

--===============1505753986==
Content-Type: multipart/alternative;
	boundary="----=_NextPart_000_002F_01C91158.E8EED410"

This is a multi-part message in MIME format.

------=_NextPart_000_002F_01C91158.E8EED410
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit

Apologies for the confusion. Build.bat and the proj.msbuild file are not
used by NUnit. Jamie
Cansdale uses them for the version he builds for TD.Net using .Net 1.0. It
has not been 
updated for 2.5, since he isn't building it yet. In fact, I don't know if he
still uses those - 
I'll check and remove them if not.
 
The NAnt build is the primary build for NUnit. To build it, enter
  nant net-2.0 build
See the comments in the nunit.build script for other options.
Note that there's a minimum NAnt version documented there as well.
 
You can also open the solutions in the VS2003, VS2005 or VS2008 directories
and build it
that way. Be sure to use the .nunit file in the same directories to run the
tests so that
the correct assemblies are referenced.
 
Hope this helps.
 
Charlie

 

  _____  

From: Simone Busoli [mailto:[email protected]] 
Sent: Sunday, September 07, 2008 11:10 PM
To: Charlie Poole
Cc: [email protected]
Subject: Re: [Nunit-users] Writing New Constraints for NUnit


Hi Charlie, no way. I did a clean checkout. Actually, I have several issues.

* If I run the build.bat I get an error saying that it cannot find the csc
compiler in the fx 1.0 folder. I don't have the fx 1.0 installed! 
* Then I tried with nant -D:default.runtime=net-2.0 but it complaints about
the SDK not being there. 
* So I tried changing nunit.proj msbuild file, setting the
TargetFrameworkVersion property to 2.0. I get the FactoriesAttribute error.
* Then I tried changing the solution the msbuild file points to from 2005 to
2008 but now the error is that a project named adhoc-tests.csproj has no
inputs specified.

Building NUnit is challenging!


On Mon, Sep 8, 2008 at 2:13 AM, Charlie Poole <[email protected]> wrote:


Yes, we're eating our own dogfood! I added a number of tests that use 2.5
features.
So using TD.Net is not possible till there's a release that supports it.
 
I think you're running into the same problem reported by somebody else on
one
of our lists - the Nant build script for nunit.framework contains an entry
for
FactoriesAttribute.cs rather than TestCases attribute. I fixed this only
recently.
 
I suggest trying to get the very latest source. If you still have problems,
let
me know so I can update CVS correctly
 
(One mistake I sometimes make is to update from within the src directory.
Make sure you do it from the top level directory to get everything.)
 
Charlie


  _____  

From: Simone Busoli [mailto:[email protected]] 
Sent: Sunday, September 07, 2008 4:17 PM
To: Charlie Poole
Cc: [email protected]
Subject: Re: [Nunit-users] Writing New Constraints for NUnit


Thanks for the guide. I'm trying to write the BinarySerializableConstraint
but I'm having some issues with building and testing NUnit. So far I had
been able to build and run tests from within VS via TD.NET, but now I
noticed that base test classes use NUnit 2.5 features so I had to rely on
something else. I tried building NUnit with nant but no success, it
complaints about missing files, specifically a Factory[something].cs. Then,
since I can run the build with VS 2008, I downloaded NUnit 2.5 alpha 3
(won't trust the build on my machine) and tried with that, but I'm getting
red all over the place in the tests for the constraints, while everything's
green for the other stuff in Tests and Syntax namespaces. At a quick look it
seems that what's failing are the tests defined in the ConstraintTestBase
class (FailsWithBadValues, ProvidesProperFailureMessage), those using the
TestCases attribute in other words.


On Sun, Sep 7, 2008 at 7:35 PM, Charlie Poole <[email protected]> wrote:


Hi All,

I've been asked to provide more info on the increasingly complicated
process of adding a new constraint to NUnit. Since I still expect
it to change - and hopefully get simpler - I'm doing it on these
mailing lists as "current but subject to change" information.

This is basically a "how-to" but I've added a postscript about
why the design is as it is at the end.

Actually, adding a constraint is easy. It's documented here:
http://nunit.org/?p=customConstraints
<http://nunit.org/?p=customConstraints&r=2.5> &r=2.5 It gets more
complicated when you also want to work with the syntax
of NUnit's fluent interface for Asserts.

I generally write constraints test first, jumping between the
tests and the constraint and between the syntax tests and
the syntactic elements. That's hard to describe, so I'll just
tell you what's needed at the end here.

1. The Constraint
I assume you're writing a simple constraint, one that does
not operate on other constraints. Inherit your constraint
class from Constraint and override the two abstract members
Match() and WriteDescriptionTo(). Be sure to set the value
of the protected field "actual" in your Match method, since
that is used in any error message. Depending on the constraint
you are writing, you might need to override other methods, but
leave them alone unless you need to do it.

If your  constraint has a generic variation, be sure to define
it within the scope of an #if NET_2_0 condition. If it operates
on any collections, try to make it work with IEnumerable
only and avoid copying the collection.

An important rule for constraints is to check for invalid
arguments and throw an exception. Do NOT just return false.
While this may work for simple cases, it will mess up more
complicated usage where constraints are combined with
various operators. And, of course, it may hide an error.

2. Constraint Tests
Derive one or more classes from ConstraintTestBase. Each of
those will be used to test one instance of the constraint.
How many you need depend on how many variations there are
within your constraint. Be sure to create separate tests
for generic variations -within an #if statement.

Write any extra tests you need, adding them to the same
classes or within a separate fixture.

NOTE: If you stop here, your constraint is useable by
creating it with new. You can write statements like:
 Assert.That( xxx, new MyConstraint(...) );

NOTE: See below if your constraint takes modifiers

3. Syntactic Elements
You will need to pick one or more key words for use
in the NUnit syntax. Pick something that will be
meaningful while keeping it reasonably short.

Currently, you must add your syntactic element in
three places. I'm looking at using code generation
to eliminate this duplication. The following
classes need to be updated:

* PartialConstraintExpression - look at how other
 simple constraints are implemented here. If
 your constraint takes modifiers, see below.
 Otherwise, you will just need a method similar
 to this one for TypeOf:

 public ConstraintExpression TypeOf(Type expectedType)
 {
   return this.Append(new ExactTypeConstraint(expectedType));
 }

* Is/Has - you decide which is better, or consult
 on the list if you're convinced that you need
 a new class. Add a method similar to this:

 public static ConstraintExpression TypeOf(Type expectedType)
 {
   return new PartialConstraintExpression().TypeOf(expectedType);
 }

* ConstraintFactory: Add a method similar to this:

 public ConstraintExpression TypeOf(Type expectedType)
 {
   return Is.TypeOf(expectedType);
 }

NOTE: It's important to keep the actual logic in the
PartialConstraintBuilder class, with the others depending
on it.

NOTE: If your constraint takes no args, use properties
rather than methods - it's easier to read.

4. Syntax Tests
Derive one or more classes from SyntaxTest. You will
need one for each different syntax you need to test.
If you forget to add code to any of the three classes
above, these tests will tell you.

At this point you're done... UNLESS you want to add
modifiers to your class. If your constraint will take
any modifiers, I suggest you do all of the above first,
then add the first one and make it work, then add
the others. Come back to this note if/when you want
to add a modifier...

Welcome Back!

In the NUnit syntax, a modifier is a property or method
that returns the object itself, after making some sort
of state change. Existing examples of modifiers are
Within(), IgnoreCase and Descending. Here's a simple
modifier:

 public EqualConstraint IgnoreCase
 {
   get { caseInsensitive = true; return this; }
 }

With the above addition, it's possible to write
 new EqualConstraint("hello").IgnoreCase
but NOT
 Is.EqualTo("hello").IgnoreCase

In order to make the syntax work, it's currently
necessary to create a ConstraintModifier class.
These classes inherit from ConstraintModifier
and are usually implemented as nested classes
within the constraint itself, so as to allow
access to private members of the constraint.

Here's a simplified version of the one for
EqualConstraint:

 public class Modifier : ConstraintModifier
 {
   private EqualConstraint constraint;

   public Modifier(EqualConstraint constraint,
                   ConstraintExpression builder)
     : base(constraint, builder)
   {
     this.constraint = constraint;
   }

   public Modifier IgnoreCase
   {
       get { constraint.caseInsensitive = true; return this; }
   }
 }

After implementing the above, the three syntax classes
need to be changed so our methods return EqualConstraint.Modifier.
ConstraintFactory and Is/Has require no further changes but
PartialConstraintExpression will now look like this:

 public EqualConstraint.Modifier EqualTo(object expected)
 {
   EqualConstraint constraint = new EqualConstraint(expected);
   return new EqualConstraint.Modifier(constraint,
this.Append(constraint));
 }

That's "all" there is to it! :-)

Charlie

Theoretical PostScript:

In case you wonder Why we neeed all the classes:

We want to provide a good object model, while *at*the*same*time*
having only reasonable choices appear in the intellisense. And
we want whatever you can compile to make sense as much as
is possible, so that there aren't too many runtime checks.

So we need separate PartialConstraintExpression and
ConstraintExpression classes to make sure you can't
enter ...And.And... or ...Null.Null... and similar
meaningless stuff.

We need Is/Has to provide static methods to get the
expression started.

We need ConstraintFactory, to supply instance methods
for use by those who prefer to derive test classes
from AssertionHelper. We could eliminnate that
class by eliminating the feature.

In particular, the Modifier classes are needed because we
are dealing with a ConstraintExpression, but want the
choices offered to the user to represent those provided
for an Equal Constraint. The Modifier class ties together
the whole expression and the "leading edge" constraint
in a way that lets us have both. If the user ends the
expression, the Modifier's implementation of IConstraint
is used. If the user types "IgnoreCase" the EqualConstraint
is used. If the user types "And" or "Or", that's handled
by the ConstraintExpression.

I'm working on a few approaches to this extra class.






-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100
<http://moblin-contest.org/redirect.php?banner_id=100&url=/> &url=/
_______________________________________________
Nunit-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/nunit-users





------=_NextPart_000_002F_01C91158.E8EED410
Content-Type: text/html;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Dus-ascii">
<META content=3D"MSHTML 6.00.6000.16705" name=3DGENERATOR></HEAD>
<BODY>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2>Apologies for the confusion. Build.bat and the proj.msbuild =
file are not=20
used by NUnit. Jamie</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2>Cansdale uses them for the version he builds for TD.Net using =
.Net 1.0.=20
</FONT></SPAN><SPAN class=3D593080309-08092008><FONT face=3DArial =
color=3D#0000ff=20
size=3D2>It has not been </FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2>updated for 2.5, </FONT></SPAN><SPAN =
class=3D593080309-08092008><FONT=20
face=3DArial color=3D#0000ff size=3D2>since he isn't building it yet. In =
fact, I don't=20
know if he still uses those - </FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>I'll=20
check and remove them if not.</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>The=20
NAnt build is the primary build for NUnit. To build it,=20
enter</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>&nbsp;=20
nant net-2.0 build</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>See=20
the comments in the nunit.build script for other =
options.</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>Note=20
that there's a minimum NAnt version documented there as=20
well.</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>You=20
can also open the solutions in the&nbsp;VS2003, VS2005 or VS2008 =
directories=20
and&nbsp;build it</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>that=20
way. Be sure to use the .nunit file in the same directories to run the =
tests so=20
that</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>the=20
correct assemblies are referenced.</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =
size=3D2>Hope=20
this helps.</FONT></SPAN></DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=3D593080309-08092008><FONT face=3DArial color=3D#0000ff =

size=3D2>Charlie</FONT></SPAN></DIV>
<DIV><FONT face=3DArial color=3D#0000ff size=3D2></FONT><BR>&nbsp;</DIV>
<BLOCKQUOTE dir=3Dltr=20
style=3D"PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #0000ff 2px =
solid; MARGIN-RIGHT: 0px">
  <DIV class=3DOutlookMessageHeader lang=3Den-us dir=3Dltr align=3Dleft>
  <HR tabIndex=3D-1>
  <FONT face=3DTahoma size=3D2><B>From:</B> Simone Busoli=20
  [mailto:[email protected]] <BR><B>Sent:</B> Sunday, September =
07, 2008=20
  11:10 PM<BR><B>To:</B> Charlie Poole<BR><B>Cc:</B>=20
  [email protected]<BR><B>Subject:</B> Re: [Nunit-users] =
Writing=20
  New Constraints for NUnit<BR></FONT><BR></DIV>
  <DIV></DIV>
  <DIV dir=3Dltr>Hi Charlie, no way. I did a clean checkout. Actually, I =
have=20
  several issues.&nbsp;
  <DIV>* If I run the build.bat I get an error saying that it cannot =
find the=20
  csc compiler in the fx 1.0 folder. I don't have the fx 1.0=20
  installed!&nbsp;</DIV>
  <DIV>* Then I tried with nant -D:default.runtime=3Dnet-2.0 but it =
complaints=20
  about the SDK not being there.
  <DIV>* So I tried changing nunit.proj msbuild file, setting=20
  the&nbsp;TargetFrameworkVersion property to 2.0. I get the =
FactoriesAttribute=20
  error.</DIV>
  <DIV>* Then I tried changing the solution the msbuild file points to =
from 2005=20
  to 2008 but now the error is that a project named adhoc-tests.csproj =
has no=20
  inputs specified.</DIV>
  <DIV><BR></DIV>
  <DIV>Building NUnit is challenging!<BR><BR>
  <DIV class=3Dgmail_quote>On Mon, Sep 8, 2008 at 2:13 AM, Charlie Poole =
<SPAN=20
  dir=3Dltr>&lt;<A=20
  href=3D"mailto:[email protected]">[email protected]</A>&gt;</SPAN> =
wrote:<BR>
  <BLOCKQUOTE class=3Dgmail_quote=20
  style=3D"PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: =
#ccc 1px solid">
    <DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>Yes, we're =
eating our own=20
    dogfood! I added a number of tests that use 2.5=20
features.</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>So using =
TD.Net is not=20
    possible till there's a release that supports =
it.</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff =
size=3D2></FONT></SPAN>&nbsp;</DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>I think =
you're running into=20
    the same problem reported by somebody else on =
one</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>of our lists =
- the Nant=20
    build script for nunit.framework contains an entry =
for</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff =
size=3D2>FactoriesAttribute.cs=20
    rather than TestCases attribute. I fixed this only=20
    recently.</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff =
size=3D2></FONT></SPAN>&nbsp;</DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>I suggest =
trying to get the=20
    very latest source. If you still have problems, =
let</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>me know so I =
can update CVS=20
    correctly</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff =
size=3D2></FONT></SPAN>&nbsp;</DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>(One mistake =
I sometimes=20
    make is to update from within the src directory.</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff size=3D2>Make sure you =
do it from=20
    the top level directory to get everything.)</FONT></SPAN></DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff =
size=3D2></FONT></SPAN>&nbsp;</DIV>
    <DIV><SPAN><FONT face=3DArial color=3D#0000ff=20
    size=3D2>Charlie</FONT></SPAN></DIV><BR>
    <BLOCKQUOTE dir=3Dltr=20
    style=3D"PADDING-LEFT: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #0000ff =
2px solid; MARGIN-RIGHT: 0px">
      <DIV lang=3Den-us dir=3Dltr align=3Dleft>
      <HR>
      <FONT face=3DTahoma size=3D2><B>From:</B> Simone Busoli [mailto:<A =

      href=3D"mailto:[email protected]"=20
      target=3D_blank>[email protected]</A>] <BR><B>Sent:</B> =
Sunday,=20
      September 07, 2008 4:17 PM<BR><B>To:</B> Charlie =
Poole<BR><B>Cc:</B> <A=20
      href=3D"mailto:[email protected]"=20
      =
target=3D_blank>[email protected]</A><BR><B>Subject:</B> =
Re:=20
      [Nunit-users] Writing New Constraints for =
NUnit<BR></FONT><BR></DIV>
      <DIV>
      <DIV></DIV>
      <DIV class=3DWj3C7c>
      <DIV></DIV>
      <DIV dir=3Dltr>Thanks for the guide. I'm trying to write the=20
      BinarySerializableConstraint but I'm having some issues with =
building and=20
      testing NUnit. So far I had been able to build and run tests from =
within=20
      VS via <A href=3D"http://TD.NET" target=3D_blank>TD.NET</A>, but =
now I noticed=20
      that base test classes use NUnit 2.5 features so I had to rely on=20
      something else. I tried building NUnit with nant but no success, =
it=20
      complaints about missing files, specifically a =
Factory[something].cs.=20
      Then, since I can run the build with VS 2008, I downloaded NUnit =
2.5 alpha=20
      3 (won't trust the build on my machine) and tried with that, but =
I'm=20
      getting red all over the place in the tests for the constraints, =
while=20
      everything's green for the other stuff in Tests and Syntax =
namespaces. At=20
      a quick look it seems that what's failing are the tests defined in =
the=20
      ConstraintTestBase class (FailsWithBadValues,=20
      ProvidesProperFailureMessage), those using the&nbsp;TestCases =
attribute in=20
      other words.<BR><BR>
      <DIV class=3Dgmail_quote>On Sun, Sep 7, 2008 at 7:35 PM, Charlie =
Poole <SPAN=20
      dir=3Dltr>&lt;<A href=3D"mailto:[email protected]"=20
      target=3D_blank>[email protected]</A>&gt;</SPAN> wrote:<BR>
      <BLOCKQUOTE class=3Dgmail_quote=20
      style=3D"PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; =
BORDER-LEFT: #ccc 1px solid">Hi=20
        All,<BR><BR>I've been asked to provide more info on the =
increasingly=20
        complicated<BR>process of adding a new constraint to NUnit. =
Since I=20
        still expect<BR>it to change - and hopefully get simpler - I'm =
doing it=20
        on these<BR>mailing lists as "current but subject to change"=20
        information.<BR><BR>This is basically a "how-to" but I've added =
a=20
        postscript about<BR>why the design is as it is at the=20
        end.<BR><BR>Actually, adding a constraint is easy. It's =
documented=20
        here:<BR><A =
href=3D"http://nunit.org/?p=3DcustomConstraints&amp;r=3D2.5"=20
        =
target=3D_blank>http://nunit.org/?p=3DcustomConstraints&amp;r=3D2.5</A> =
It=20
        gets more<BR>complicated when you also want to work with the=20
        syntax<BR>of NUnit's fluent interface for Asserts.<BR><BR>I =
generally=20
        write constraints test first, jumping between the<BR>tests and =
the=20
        constraint and between the syntax tests and<BR>the syntactic =
elements.=20
        That's hard to describe, so I'll just<BR>tell you what's needed =
at the=20
        end here.<BR><BR>1. The Constraint<BR>I assume you're writing a =
simple=20
        constraint, one that does<BR>not operate on other constraints. =
Inherit=20
        your constraint<BR>class from Constraint and override the two =
abstract=20
        members<BR>Match() and WriteDescriptionTo(). Be sure to set the=20
        value<BR>of the protected field "actual" in your Match method,=20
        since<BR>that is used in any error message. Depending on the=20
        constraint<BR>you are writing, you might need to override other =
methods,=20
        but<BR>leave them alone unless you need to do it.<BR><BR>If your =

        &nbsp;constraint has a generic variation, be sure to =
define<BR>it within=20
        the scope of an #if NET_2_0 condition. If it operates<BR>on any=20
        collections, try to make it work with IEnumerable<BR>only and =
avoid=20
        copying the collection.<BR><BR>An important rule for constraints =
is to=20
        check for invalid<BR>arguments and throw an exception. Do NOT =
just=20
        return false.<BR>While this may work for simple cases, it will =
mess up=20
        more<BR>complicated usage where constraints are combined =
with<BR>various=20
        operators. And, of course, it may hide an error.<BR><BR>2. =
Constraint=20
        Tests<BR>Derive one or more classes from ConstraintTestBase. =
Each=20
        of<BR>those will be used to test one instance of the =
constraint.<BR>How=20
        many you need depend on how many variations there are<BR>within =
your=20
        constraint. Be sure to create separate tests<BR>for generic =
variations=20
        -within an #if statement.<BR><BR>Write any extra tests you need, =
adding=20
        them to the same<BR>classes or within a separate =
fixture.<BR><BR>NOTE:=20
        If you stop here, your constraint is useable by<BR>creating it =
with new.=20
        You can write statements like:<BR>&nbsp;Assert.That( xxx, new=20
        MyConstraint(...) );<BR><BR>NOTE: See below if your constraint =
takes=20
        modifiers<BR><BR>3. Syntactic Elements<BR>You will need to pick =
one or=20
        more key words for use<BR>in the NUnit syntax. Pick something =
that will=20
        be<BR>meaningful while keeping it reasonably =
short.<BR><BR>Currently,=20
        you must add your syntactic element in<BR>three places. I'm =
looking at=20
        using code generation<BR>to eliminate this duplication. The=20
        following<BR>classes need to be updated:<BR><BR>*=20
        PartialConstraintExpression - look at how other<BR>&nbsp;simple=20
        constraints are implemented here. If<BR>&nbsp;your constraint =
takes=20
        modifiers, see below.<BR>&nbsp;Otherwise, you will just need a =
method=20
        similar<BR>&nbsp;to this one for TypeOf:<BR><BR>&nbsp;public=20
        ConstraintExpression TypeOf(Type =
expectedType)<BR>&nbsp;{<BR>&nbsp;=20
        &nbsp;return this.Append(new=20
        ExactTypeConstraint(expectedType));<BR>&nbsp;}<BR><BR>* Is/Has - =
you=20
        decide which is better, or consult<BR>&nbsp;on the list if =
you're=20
        convinced that you need<BR>&nbsp;a new class. Add a method =
similar to=20
        this:<BR><BR>&nbsp;public static ConstraintExpression =
TypeOf(Type=20
        expectedType)<BR>&nbsp;{<BR>&nbsp; &nbsp;return new=20
        =
PartialConstraintExpression().TypeOf(expectedType);<BR>&nbsp;}<BR><BR>*=20
        ConstraintFactory: Add a method similar to =
this:<BR><BR>&nbsp;public=20
        ConstraintExpression TypeOf(Type =
expectedType)<BR>&nbsp;{<BR>&nbsp;=20
        &nbsp;return Is.TypeOf(expectedType);<BR>&nbsp;}<BR><BR>NOTE: =
It's=20
        important to keep the actual logic in =
the<BR>PartialConstraintBuilder=20
        class, with the others depending<BR>on it.<BR><BR>NOTE: If your=20
        constraint takes no args, use properties<BR>rather than methods =
- it's=20
        easier to read.<BR><BR>4. Syntax Tests<BR>Derive one or more =
classes=20
        from SyntaxTest. You will<BR>need one for each different syntax =
you need=20
        to test.<BR>If you forget to add code to any of the three=20
        classes<BR>above, these tests will tell you.<BR><BR>At this =
point you're=20
        done... UNLESS you want to add<BR>modifiers to your class. If =
your=20
        constraint will take<BR>any modifiers, I suggest you do all of =
the above=20
        first,<BR>then add the first one and make it work, then =
add<BR>the=20
        others. Come back to this note if/when you want<BR>to add a=20
        modifier...<BR><BR>Welcome Back!<BR><BR>In the NUnit syntax, a =
modifier=20
        is a property or method<BR>that returns the object itself, after =
making=20
        some sort<BR>of state change. Existing examples of modifiers=20
        are<BR>Within(), IgnoreCase and Descending. Here's a=20
        simple<BR>modifier:<BR><BR>&nbsp;public EqualConstraint=20
        IgnoreCase<BR>&nbsp;{<BR>&nbsp; &nbsp;get { caseInsensitive =3D =
true;=20
        return this; }<BR>&nbsp;}<BR><BR>With the above addition, it's =
possible=20
        to write<BR>&nbsp;new EqualConstraint("hello").IgnoreCase<BR>but =

        NOT<BR>&nbsp;Is.EqualTo("hello").IgnoreCase<BR><BR>In order to =
make the=20
        syntax work, it's currently<BR>necessary to create a =
ConstraintModifier=20
        class.<BR>These classes inherit from ConstraintModifier<BR>and =
are=20
        usually implemented as nested classes<BR>within the constraint =
itself,=20
        so as to allow<BR>access to private members of the=20
        constraint.<BR><BR>Here's a simplified version of the one=20
        for<BR>EqualConstraint:<BR><BR>&nbsp;public class Modifier :=20
        ConstraintModifier<BR>&nbsp;{<BR>&nbsp; &nbsp;private =
EqualConstraint=20
        constraint;<BR><BR>&nbsp; &nbsp;public Modifier(EqualConstraint=20
        constraint,<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp;=20
        &nbsp; &nbsp;ConstraintExpression builder)<BR>&nbsp; &nbsp; =
&nbsp;:=20
        base(constraint, builder)<BR>&nbsp; &nbsp;{<BR>&nbsp; &nbsp;=20
        &nbsp;this.constraint =3D constraint;<BR>&nbsp; =
&nbsp;}<BR><BR>&nbsp;=20
        &nbsp;public Modifier IgnoreCase<BR>&nbsp; &nbsp;{<BR>&nbsp; =
&nbsp;=20
        &nbsp; &nbsp;get { constraint.caseInsensitive =3D true; return =
this;=20
        }<BR>&nbsp; &nbsp;}<BR>&nbsp;}<BR><BR>After implementing the =
above, the=20
        three syntax classes<BR>need to be changed so our methods return =

        EqualConstraint.Modifier.<BR>ConstraintFactory and Is/Has =
require no=20
        further changes but<BR>PartialConstraintExpression will now look =
like=20
        this:<BR><BR>&nbsp;public EqualConstraint.Modifier =
EqualTo(object=20
        expected)<BR>&nbsp;{<BR>&nbsp; &nbsp;EqualConstraint constraint =
=3D new=20
        EqualConstraint(expected);<BR>&nbsp; &nbsp;return new=20
        =
EqualConstraint.Modifier(constraint,<BR>this.Append(constraint));<BR>&nbs=
p;}<BR><BR>That's=20
        "all" there is to it! :-)<BR><BR>Charlie<BR><BR>Theoretical=20
        PostScript:<BR><BR>In case you wonder Why we neeed all the=20
        classes:<BR><BR>We want to provide a good object model, while=20
        *at*the*same*time*<BR>having only reasonable choices appear in =
the=20
        intellisense. And<BR>we want whatever you can compile to make =
sense as=20
        much as<BR>is possible, so that there aren't too many runtime=20
        checks.<BR><BR>So we need separate PartialConstraintExpression=20
        and<BR>ConstraintExpression classes to make sure you =
can't<BR>enter=20
        ...And.And... or ...Null.Null... and similar<BR>meaningless=20
        stuff.<BR><BR>We need Is/Has to provide static methods to get=20
        the<BR>expression started.<BR><BR>We need ConstraintFactory, to =
supply=20
        instance methods<BR>for use by those who prefer to derive test=20
        classes<BR>from AssertionHelper. We could eliminnate =
that<BR>class by=20
        eliminating the feature.<BR><BR>In particular, the Modifier =
classes are=20
        needed because we<BR>are dealing with a ConstraintExpression, =
but want=20
        the<BR>choices offered to the user to represent those =
provided<BR>for an=20
        Equal Constraint. The Modifier class ties together<BR>the whole=20
        expression and the "leading edge" constraint<BR>in a way that =
lets us=20
        have both. If the user ends the<BR>expression, the Modifier's=20
        implementation of IConstraint<BR>is used. If the user types =
"IgnoreCase"=20
        the EqualConstraint<BR>is used. If the user types "And" or "Or", =
that's=20
        handled<BR>by the ConstraintExpression.<BR><BR>I'm working on a =
few=20
        approaches to this extra=20
        =
class.<BR><BR><BR><BR><BR><BR><BR>---------------------------------------=
----------------------------------<BR>This=20
        SF.Net email is sponsored by the Moblin Your Move Developer's=20
        challenge<BR>Build the coolest Linux based applications with =
Moblin SDK=20
        &amp; win great prizes<BR>Grand prize is a trip for two to an =
Open=20
        Source event anywhere in the world<BR><A=20
        =
href=3D"http://moblin-contest.org/redirect.php?banner_id=3D100&amp;url=3D=
/"=20
        =
target=3D_blank>http://moblin-contest.org/redirect.php?banner_id=3D100&am=
p;url=3D/</A><BR>_______________________________________________<BR>Nunit=
-users=20
        mailing list<BR><A =
href=3D"mailto:[email protected]"=20
        target=3D_blank>[email protected]</A><BR><A=20
        =
href=3D"https://lists.sourceforge.net/lists/listinfo/nunit-users"=20
        =
target=3D_blank>https://lists.sourceforge.net/lists/listinfo/nunit-users<=
/A><BR></BLOCKQUOTE></DIV><BR></DIV></DIV></DIV></BLOCKQUOTE></DIV></BLOC=
KQUOTE></DIV><BR></DIV></DIV></DIV></BLOCKQUOTE></BODY></HTML>

------=_NextPart_000_002F_01C91158.E8EED410--





--===============1505753986==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
--===============1505753986==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Nunit-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/nunit-users

--===============1505753986==--