Support for @Theory and @DataPoint?

7 views
Skip to first unread message

Sean Corfield

unread,
Oct 23, 2009, 8:08:30 PM10/23/09
to mxu...@googlegroups.com
At CFinNC I saw Michael Labriola present Flex Unit 4. It's "4" because
it more closely matches JUnit 4.x, not because of any association with
Flex 4 (although Flex Unit 4 support is built into Flash Builder 4
Beta 2).

Anyway, he showed how the test runner was now parameterized as an
annotation allowing Flex Unit 4 suites to run unit tests based on
*any* unit testing framework (very cool). That's also how Flash
Builder integrates with Flex Unit 4 - it uses a runner that opens a
socket connection to Flash Builder itself to communicate results.

The other thing he showed blew me away: theories!

These are parameterized test methods which the framework runs for all
combinations of data points provided. E.g., if you mark a test method
as @Theory and it takes two numeric arguments, and you provide an
array of 0 .. 9 as one the @DataPoint values, the framework runs the
method for (0,0), (0,1), (0,2) .. (1,0), (1,1), (1,2) .. (9,7), (9,8),
(9,9) - all 100 possible combinations.

In Flex Unit 4, it pulls together all the @DataPoint objects it finds
and aggregates them by type (including calling methods marked as
@DataPoint to dynamically retrieve more test values). Then, when it
hits a @Theory, it introspects the types of the arguments and then
iterates over the method for all combinations of data points that
matches the types of the arguments to the theory.

This can dramatically reduce the number of test cases you have to
write to achieve coverage in many situations as well as improve code
coverage beyond anything you would other manually write.

I'd love to see something like this added to MXUnit!

Case in point, I've just written 16 test cases (that actually test 28
assertions) and I could have cut this down to just two test cases if
I'd had theories!
--
Sean A Corfield -- (904) 302-SEAN
Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

Bob Silverberg

unread,
Oct 23, 2009, 9:06:14 PM10/23/09
to mxu...@googlegroups.com
This sounds kind of similar to the dataproviders that the boys are currently working on.  Is it?
--
Bob Silverberg
www.silverwareconsulting.com

billy

unread,
Oct 23, 2009, 9:27:10 PM10/23/09
to mxunit
Sean,

I like that! I remember Kent Beck tweeting about it a while back and
have been following JUnit at github: http://github.com/KentBeck/junit/issues.
Though, admittedly, I just glazed over the data point/theory concepts
but will look into it for sure. ::::: segue --> I personally like
iterative approaches and power testing (fuzzy testing and the like),
and a related feature we're very close to releasing is a @Dataprovider
annotation (inspired by Cédic Buest/TestNG). This is similar, but not
as intelligent, however, it will allow you to specify various data to
drive your tests. These can be queries, arrays, lists, and excel/csv
files - we're still working out some of the excel file details. So,
maybe this will server as a teaser of sorts. Example:

<cffunction name="testSomething" mxunit:dataprovider="queryName">
<cfargument name="q" />
<cfset o = createObject( 'component', 'com.foo.bar' ).init
( q.colum1 );
<cfset foo = o.doSomething( q.colum2 * q.colum3) />
<cfset assert ( foo ) />
....
</cffunction>

The mxunit:dataprovider accepts arrays and lists, too. And if you just
want to run something 100,000 times for grins, you could do this:

<cffunction name="testSomething" mxunit:dataprovider="100000">
<cfargument name="num" />
<cfset rn = generateRandomString( seed=rand(num) ) />
<cfset assert( obj.isSufficientlyRandom(rn) ) />
</cffunction>

Any comments and suggestions are welcome.

bill
> Railo Technologies US --http://getrailo.com/
> An Architect's View --http://corfield.org/

Sean Corfield

unread,
Oct 24, 2009, 12:38:32 AM10/24/09
to mxu...@googlegroups.com
On Fri, Oct 23, 2009 at 6:27 PM, billy <vir...@gmail.com> wrote:
> <cffunction name="testSomething" mxunit:dataprovider="queryName">
>  <cfargument name="q" />
>  <cfset o =  createObject( 'component', 'com.foo.bar' ).init
> (  q.colum1 );
>  <cfset foo = o.doSomething( q.colum2 * q.colum3) />
>  <cfset assert ( foo ) />
>  ....
> </cffunction>

That's pretty close... now if you could do this as well:

<cffunction name="testSomething">
<cfargument name="q" mxunit:dataprovider="queryName"/>
<cfargument name="id" mxunit:dataprovider="userIdList"/>
...
</cffunction>


--
Sean A Corfield -- (904) 302-SEAN

Railo Technologies US -- http://getrailo.com/
An Architect's View -- http://corfield.org/

Mark Mandel

unread,
Oct 24, 2009, 1:46:54 AM10/24/09
to mxu...@googlegroups.com
I would just like to say - this stuff sounds *awesome*.

Keep up the good work.

Mark
--
E: mark....@gmail.com
T: http://www.twitter.com/neurotic
W: www.compoundtheory.com

Reply all
Reply to author
Forward
0 new messages