tag:blogger.com,1999:blog-90239442051008034142008-10-01T04:25:51.276-07:00Bits in MotionMuch Ado About CodeJeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comBlogger102125tag:blogger.com,1999:blog-9023944205100803414.post-72912552858689333242008-09-19T02:01:00.001-07:002008-09-19T02:01:00.724-07:00Quickie<p>Sorry for the long silence.  I've been super busy lately.</p> <p>Anyways... I'll tantalize you with this: <a href="http://www.gallio.org/" target="_blank">Gallio</a> v3.0.4 is almost ready to ship.  We're just cleaning up some loose ends and putting on the finishing touches.</p> <p>I am really looking forward to making the final announcement.  There's lots of cool (and useful) new stuff on the way!</p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-4798216856353681712008-08-22T14:30:00.001-07:002008-08-22T14:30:59.868-07:00How to Find Me<p>I live in the East Bay and work in San Francisco.  I'm always keen on meeting smart and interesting people.  If you're local and would like to hang out, shoot me an email.</p> <h4>Upcoming Conferences</h4> <h5>November 17th-21st: QCon</h5> <p>On Thursday I'll be giving a <a href="http://qconsf.com/sf2008/speaker/Jeff+Brown">talk</a> about Gallio and MbUnit at <a href="http://qconsf.com/sf2008/conference/">QCon</a> in the ALT.Net track.  I'm planning to talk about the architecture of Gallio and demonstrate a few ways that it can be extended to build new test tools. I will also discuss how MbUnit integrates with Gallio and how other test frameworks can do the same.</p> <h5>November 8th-9th: Silicon Valley Code Camp</h5> <p>I'm planning to attend <a href="http://www.siliconvalley-codecamp.com/Default.aspx">Silicon Valley Code Camp</a>, a free conference in the Bay Area.  I've also signed up to give a talk similar to the one at QCon.  Looks like a great opportunity to meet more local talent.</p> <h4>Community Events</h4> <p>I sing Tenor with <a href="http://www.sfcitychorus.org/">San Francisco City Chorus</a>, a local amateur choir.  It's a lot of fun and we're always looking for new members.</p> <p>My wife and I also sing with the <a href="http://www.mduuc.org/home/home.html">Mount Diablo Unitarian Universalist Church</a>.  I'm still not sure about this whole "church" thing, but it's a nice community of <strike>hippies</strike> genuine, empathetic, forward-thinking, individualists.</p> <p>I used to do English Country dancing with the <a href="http://rgoldman.org/pryanksters/index.htm">Merrie Pryanksters</a> at the California Renaissance Faires and do Irish dancing at the <a href="http://www.starryploughpub.com/history/">Starry Plough Pub</a> in Berkeley.  Lately my participation has been superceded by other activities but I still hang out.</p> <p>Occasionally you'll find me hanging out with other Canadian members of the <a href="http://www.digitalmooselounge.com/">Digital Moose Lounge</a> at a hockey game or Canada Day picnic.</p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-48990268147847504502008-08-21T06:25:00.001-07:002008-08-21T06:29:35.596-07:00Diffs in Assertion Failures<p>Just one of many features I've been working on lately.</p> <p>More to come... now it's wayyy past bedtime.</p> <h4></h4> <h4>Spot the Case-Change</h4> <p><a href="http://lh5.ggpht.com/jeff.brown/SK1tvLJjA4I/AAAAAAAAAMQ/EFmw7Of6QNg/s1600-h/image%5B11%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="219" alt="image" src="http://lh6.ggpht.com/jeff.brown/SK1tvmLyXBI/AAAAAAAAAMU/mQHSn-DhY54/image_thumb%5B5%5D.png?imgmax=800" width="748" border="0" /></a></p> <h4>Something More Complex</h4> <p><a href="http://lh3.ggpht.com/jeff.brown/SK1svYw016I/AAAAAAAAAMI/HXmi4oAg3js/s1600-h/image%5B3%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="362" alt="image" src="http://lh4.ggpht.com/jeff.brown/SK1sv1zHUII/AAAAAAAAAMM/wwBUCQUE0GQ/image_thumb%5B1%5D.png?imgmax=800" width="758" border="0" /></a> </p> <p>I'm considering using strike-through to give added emphasis to changed or deleted text from the expected value.  What do you think?</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:115e8004-075e-4082-9cda-73f545d53b83" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-59304467638149273712008-07-15T16:12:00.001-07:002008-07-15T16:12:47.610-07:00Getting Stuff Done<p>Liz and I have to move next month.  The landlady simply wants to move back into her house so she will not renew the lease.</p> <p>Thus begins the process of dismantling <a href="http://www.randsinrepose.com/archives/2006/07/10/a_nerd_in_a_cave.html">The Cave</a> and going somewhere else.  But where?  We have searched all over for homes to buy or to rent over the past two months and have not found anything acceptable yet.</p> <p>A small part of me would like nothing more than for someone else (perhaps my employer) to take care of these details so I can move on with the process of getting stuff done.  Foolishness!  Alas.</p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-25708192612736456802008-07-09T16:44:00.001-07:002008-07-09T18:14:40.648-07:00Attribution and the Golden Rule<p>Gallio uses the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p> <p>Today I discovered a breach of that license wherein an author of another Open Source project copied code from Gallio and removed the copyright notices and attribution.</p> <p>I have contacted the author and hope to resolve the matter amicably.</p> <h4>Giving Credit Where it is Due</h4> <p>You may have noticed that I take pains to acknowledge the work of others when I borrow their ideas.  For example, I credit <a href="http://www.codeplex.com/xunit">xUnit.Net</a> for their idea of abstracting the reflection layer (among other things).  That simple idea has shaped a fair bit of the Gallio test object model so I'm grateful to have encountered it.</p> <p>On an even grander scale, there are many others whom I credit for the development of unit testing and the idiomatic form it has taken in .Net.  MbUnit borrows heavily from <a href="http://www.nunit.org/" target="_blank">NUnit</a>, <a href="http://junit.sourceforge.net/" target="_blank">JUnit</a> and other frameworks, not to mention the work of Kent Beck and other <a href="http://www.martinfowler.com/bliki/Xunit.html" target="_blank">founders</a>.</p> <h4>Professional Courtesy</h4> <p>Recently I have noticed others borrowing ideas from Gallio and MbUnit.  I think it's great!  Imitation is the sincerest form of flattery.  But I do feel something is missing.</p> <p>Open Source software does not get built in a vacuum.  There are many people involved in the conception, development, promotion and distribution of software.  We depend crucially upon the goodwill of others and so it behooves us to act with humility and respect for one another and our respective projects.</p> <p>The more widely we disseminate the good ideas of others, the more positive impact they will have.</p> <p>Thanks.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d1f235f6-7501-42d5-9d3e-27b4bc9e9899" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a>,<a href="http://technorati.com/tags/values" rel="tag">values</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-17580936677855027072008-06-17T01:57:00.001-07:002008-06-17T01:57:39.666-07:00Announcing Gallio Alpha 3 Update 3<p>Here comes the next update to Gallio and MbUnit v3.</p> <p>This is an interim release with a few new features and updates.</p> <p>Download here: (<a href="http://mb-unit.googlecode.com/files/GallioBundle-3.0.0.285-Setup.exe">link</a>)</p> <h2>New and Noteworthy</h2> <h3>ReSharper v4.0 Final Integration</h3> <p>This update now supports the final release of ReSharper v4.0.</p> <p>Enjoy!</p> <h3>MbUnit [Factory] Attribute</h3> <p>Suppose we've got a function like this:</p> <p><a href="http://lh6.ggpht.com/jeff.brown/SFd8a-InrXI/AAAAAAAAALI/EII18qdF0j8/s1600-h/image%5B22%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="159" alt="image" src="http://lh4.ggpht.com/jeff.brown/SFd8b99tHiI/AAAAAAAAALM/IAqR3it1QdA/image_thumb%5B10%5D.png?imgmax=800" width="433" border="0" /></a> </p> <p>To test it, we'll need some different kinds of objects.</p> <p>So let's use a factory:</p> <p><a href="http://lh3.ggpht.com/jeff.brown/SFd8cM3j29I/AAAAAAAAALQ/dCu1d235pK4/s1600-h/image%5B26%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="259" alt="image" src="http://lh5.ggpht.com/jeff.brown/SFd8cs6DCVI/AAAAAAAAALU/ByDR2GEbRWM/image_thumb%5B12%5D.png?imgmax=800" width="462" border="0" /></a> </p> <p>That's quite simple, assuming we only want to use single objects for each run.</p> <p>But we can do better.  We can also return arrays of objects:</p> <p><a href="http://lh3.ggpht.com/jeff.brown/SFd8c0JkqjI/AAAAAAAAALY/olZIf8mH3bk/s1600-h/image%5B31%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="275" alt="image" src="http://lh4.ggpht.com/jeff.brown/SFd8dDAcENI/AAAAAAAAALc/Di5mIgGJzf0/image_thumb%5B15%5D.png?imgmax=800" width="529" border="0" /></a> </p> <p>However, this doesn't test the case where the value was null.  In that case, the formatter function is supposed to throw an ArgumentNullException.</p> <p>We can simulate the behavior of the [ExpectedException] attribute by returning additional metadata along with the data item.  Of course, we can include other metadata too, like test descriptions, and other data.</p> <p><a href="http://lh5.ggpht.com/jeff.brown/SFd8dbsMZxI/AAAAAAAAALg/u93PHeX2kGE/s1600-h/image%5B35%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="308" alt="image" src="http://lh3.ggpht.com/jeff.brown/SFd8d2nMUII/AAAAAAAAALk/JDC5x2rmJDw/image_thumb%5B17%5D.png?imgmax=800" width="592" border="0" /></a> </p> <p> </p> <h3>MbUnit [Repeat] and [ThreadedRepeat] Attributes</h3> <p>Sometimes when testing features with non-deterministic behavior, it's useful to be able to run a test repeatedly.</p> <p>Use the [Repeat] and [ThreadedRepeat] attributes in MbUnit to run tests sequentially or concurrently. </p> <p>Since the attribute is a test decorator, it may be used with most any kind of test, including data-driven tests.  It can also be used on fixtures, if you like.</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SFd8eOCQeQI/AAAAAAAAALo/RavB3Fw83x8/s1600-h/image%5B3%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="309" alt="image" src="http://lh3.ggpht.com/jeff.brown/SFd8edMy3wI/AAAAAAAAALs/3_zX0mBRA-8/image_thumb%5B1%5D.png?imgmax=800" width="461" border="0" /></a> </p> <p>Each run appears as a separate item in the report.  They are considered dynamic test steps that are nested within the test. </p> <p><a href="http://lh4.ggpht.com/jeff.brown/SFd8eww9API/AAAAAAAAALw/xhEw9lLoicM/s1600-h/image%5B18%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="291" alt="image" src="http://lh3.ggpht.com/jeff.brown/SFd8fDqH90I/AAAAAAAAAL0/VJfI8nZTGYQ/image_thumb%5B8%5D.png?imgmax=800" width="466" border="0" /></a> </p> <h3>CSV Files with Metadata</h3> <p>Several people have requested the ability to include additional metadata in rows that are specified by CSV files using the [CsvData] attribute in MbUnit.</p> <p>Now you can.</p> <p>Just enclose the name of the column that contains metadata with '[' and ']' and that column will be exposed as a metadata item whose key is the name of the column.</p> <p>So given this test:</p> <p><a href="http://lh6.ggpht.com/jeff.brown/SFd8fnjIeCI/AAAAAAAAAL4/kp9vY9xz0Uc/s1600-h/image%5B42%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="107" alt="image" src="http://lh6.ggpht.com/jeff.brown/SFd8f6GLsiI/AAAAAAAAAL8/pO4-KPOD5fs/image_thumb%5B20%5D.png?imgmax=800" width="600" border="0" /></a> </p> <p>And this data file:</p> <blockquote> <p>Item, Price, [ConsumedBy] <br />Apples, 1.00, Worm <br />Bananas, 1.50, Monkey <br />Cookies, 2.00, "Cookie Monster"</p> </blockquote> <p>We get this output in the report:</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SFd8gTUv5PI/AAAAAAAAAMA/CIzI40H3s5k/s1600-h/image%5B47%5D.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="199" alt="image" src="http://lh5.ggpht.com/jeff.brown/SFd8gs0DOdI/AAAAAAAAAME/mpIYiRZXYS4/image_thumb%5B23%5D.png?imgmax=800" width="503" border="0" /></a> </p> <p>Notice that the metadata appears in the report as well as the name of the resource and the line number where the data came from!</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:18d847ff-5947-41ad-8f39-6fb9fc63c081" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-4560395830961102022008-06-10T01:46:00.001-07:002008-06-10T01:49:44.147-07:00Gallio and ReSharper 4.0<p>A few people have asked when Gallio will support the final release of ReSharper 4.0.</p> <p>Unfortunately there were some last-minute breaking changes between ReSharper 4.0 Beta and the Final release.  So the ReSharper plugin in Gallio Alpha 3 Update 2 will not work anymore.</p> <p>No matter... we plan to release another update of Gallio <em>later this week</em>.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c86b8c6f-7d1d-4f07-af95-35e2fc188298" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-33360353842550114182008-05-29T01:08:00.001-07:002008-05-29T01:08:48.705-07:00Announcing Gallio Alpha 3 Update 2<p>Today we are releasing an update to Gallio Alpha 3 with a few new features.</p> <p>Download here: (<a href="http://www.gallio.org/files/GallioBundle-3.0.0.258-Setup.exe">link</a>)</p> <h2>New and Noteworthy</h2> <h3>ReSharper v4.0 Beta Integration</h3> <p>If you haven't already heard, ReSharper v4.0 Beta is out!  (<a href="http://www.jetbrains.com/resharper/beta/beta.html">link</a>)</p> <p>And now we have support for it...</p> <h3>Gallio Test Report Action in ReSharper</h3> <p>ReSharper's unit test explorer is a great tool but it does not currently support all of the features needed for full native integration with Gallio.</p> <p>For example, there is no way for us to display embedded images -- such as screenshots -- as part of the test output.  There are also some limitations as to how we can present the results of data-driven tests -- like Row-based tests -- in ReSharper.</p> <p>No matter.  We have now added a custom action to display the full Gallio Test Report.</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SD5keyKym4I/AAAAAAAAAJI/-Daz9mQJbz4/s1600-h/image12.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="260" alt="image" src="http://lh4.ggpht.com/jeff.brown/SD5kfyKym5I/AAAAAAAAAJQ/erVQCQZm4Qw/image_thumb6.png?imgmax=800" width="644" border="0" /></a> </p> <p>We have also made a few other small improvements to the output.</p> <p>Unfortunately stack traces still are not clickable and there does not seem to be much we can do about it just now due to ReSharper limitations.</p> <h3>Pex Integration for MbUnit</h3> <p>Microsoft Pex has finally be released!  (<a href="http://research.microsoft.com/pex/">link</a>)</p> <p>We already had support for an earlier prerelease version of Pex but we have now upgraded it to the latest edition.</p> <p>The basic idea is that you can write parameterized tests using MbUnit v3 syntax and run Pex against them to generate test cases.</p> <h4>Step 1: Add a reference to MbUnit.Pex.</h4> <p><a href="http://lh5.ggpht.com/jeff.brown/SD5kgCKym6I/AAAAAAAAAJY/IuhWcx9aEow/s1600-h/image26.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="197" alt="image" src="http://lh6.ggpht.com/jeff.brown/SD5kgSKym7I/AAAAAAAAAJg/G2Wi4jlZr1I/image_thumb12.png?imgmax=800" width="218" border="0" /></a> </p> <h4>Step 2: Add the MbUnit Pex package attribute to your test assembly.</h4> <p><a href="http://lh3.ggpht.com/jeff.brown/SD5kgiKym8I/AAAAAAAAAJo/iEVn3YVk5Hs/s1600-h/image16.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="43" alt="image" src="http://lh4.ggpht.com/jeff.brown/SD5kgyKym9I/AAAAAAAAAJw/kKfZ1jshItc/image_thumb8.png?imgmax=800" width="273" border="0" /></a> </p> <h4>Step 3: Give Pex something to chew on.</h4> <p><a href="http://lh4.ggpht.com/jeff.brown/SD5kgyKym-I/AAAAAAAAAJ4/vNFXglMX-W8/s1600-h/image20.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="185" alt="image" src="http://lh5.ggpht.com/jeff.brown/SD5khCKym_I/AAAAAAAAAKA/MR_LhpnMmNo/image_thumb10.png?imgmax=800" width="437" border="0" /></a> </p> <h4>Step 4: Pex It!</h4> <p><a href="http://lh6.ggpht.com/jeff.brown/SD5khSKynAI/AAAAAAAAAKI/QASTlLvyQqU/s1600-h/image23.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="53" alt="image" src="http://lh3.ggpht.com/jeff.brown/SD5khiKynBI/AAAAAAAAAKQ/ePNWgiURvAw/image_thumb11.png?imgmax=800" width="185" border="0" /></a> </p> <h4>Step 5: Examine the generated tests.</h4> <p><a href="http://lh4.ggpht.com/jeff.brown/SD5khyKynCI/AAAAAAAAAKY/t_I5yB4wEvY/s1600-h/image30.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="229" alt="image" src="http://lh3.ggpht.com/jeff.brown/SD5kiiKynDI/AAAAAAAAAKg/1oCtAPmQXhg/image_thumb14.png?imgmax=800" width="435" border="0" /></a> </p> <p>There you go!</p> <h3>MbUnit v3 Contract Verifiers</h3> <p>I've added a couple of test fixtures to help verify common contracts such as equality and correct exception implementation.</p> <p>Currently you use these verifiers by creating subclasses.  However, I'm tempted to transform the verifiers into mixins in the long run.</p> <h4>EqualityContractVerifier</h4> <p>This checks Equals, GetHashCode(), IEquatable<T>.Equals(), operator== and operator!=.  You just need to provide the verifier with suitable distinct instances of your type.</p> <p><a href="http://lh5.ggpht.com/jeff.brown/SD5kjCKynEI/AAAAAAAAAKo/hmbDDAzBhhw/s1600-h/image34.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="213" alt="image" src="http://lh3.ggpht.com/jeff.brown/SD5kjiKynFI/AAAAAAAAAKw/ih8jvF7hf80/image_thumb16.png?imgmax=800" width="646" border="0" /></a> </p> <h4>ExceptionContractVerifier</h4> <p>This checks that an exception is serializable and has the standard constructors.</p> <p><a href="http://lh3.ggpht.com/jeff.brown/SD5kjiKynGI/AAAAAAAAAK4/sZfJ_kUFmZo/s1600-h/image38.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="55" alt="image" src="http://lh4.ggpht.com/jeff.brown/SD5kjyKynHI/AAAAAAAAALA/iazS9wlY9Ck/image_thumb18.png?imgmax=800" width="551" border="0" /></a></p> <h2> Upcoming Stuff</h2> <p>There's a bunch of new stuff on the way in Alpha 4 as we march onwards to feature-completeness.</p> <p>Here's a little list to whet your appetite:</p> <ul> <li>First partial draft of the Gallio Book.</li> <li>Constraints framework.</li> <li>Improved assertions.</li> <li>.Net 3.5 features.</li> <li>Workspace model for managing test project resources like historical test reports.</li> <li>Metadata in CSV files.</li> <li>[Factory] attribute for easier implementation of custom data sources.</li> <li>New plug-in model and performance optimizations (might slip to Alpha 5).</li> </ul> <p>I'm aware that there are a number of pending bugs and feature requests for the standard Gallio GUI (Icarus).  If you're interested in giving Graham a hand with this please let me know!</p> <p>Ditto for the Visual Studio Team System integration.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:798a6fbc-2010-4dee-a2e2-39a2dfd3859b" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a>,<a href="http://technorati.com/tags/gallio" rel="tag">gallio</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-44859585392187791042008-05-27T16:30:00.001-07:002008-05-27T16:30:42.932-07:00Help wanted: Release and Promotion Manager for Gallio and MbUnit<p>I'm looking for a volunteer to help release and promote new editions of Gallio and MbUnit.</p> <p>If this sounds like something that would interest you, please let me know.</p> <p>Thanks!</p> <h4>Release and Promotion Manager</h4> <p>Responsibilities:</p> <ul> <li>Draft the release criteria.</li> <li>Ensure the release criteria have been met.</li> <li>Publish the release notes and release files.</li> <li>Keep the website updated with news and useful resources.</li> <li>Promote Gallio and MbUnit online and in the local community.</li> <li>Produce articles, tutorials, podcasts, and other educational or promotional materials.</li> <li>Monitor reactions from users and use it to steer subsequent releases.</li> </ul> <p>Salary:  Cookies, chocolate, beer or other treat of your choice.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b3ff1584-595b-4719-bd94-a616b65f4cfc" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-32419808746843354302008-05-19T17:56:00.001-07:002008-05-19T17:56:40.699-07:00MSBuild v3.5 ToolsVersion Attribute Gotchas<p>I just spent an hour debugging a project trying to use the new Properties and AdditionalProperties metadata in MSBuild v3.5.  (<a href="http://msdn.microsoft.com/en-us/library/z7f65y0d.aspx">MSDN</a>)</p> <p>This special metadata is used to pass properties to MSBuild projects that are invoked using the MSBuild task.</p> <h4>Example</h4> <p><strong>a.proj</strong></p> <blockquote> <p><Project DefaultTargets="Test" xmlns="<a href="http://schemas.microsoft.com/developer/msbuild/2003"">http://schemas.microsoft.com/developer/msbuild/2003"</a> ToolsVersion="3.5"> <br />  <ItemGroup> <br />    <Project Include="b.proj"> <br />      <Properties>Foo=123</Properties> <br />    </Project> <br />  </ItemGroup> </p> <p>  <Target Name="Test"> <br />    <MSBuild Projects="@(Project)" /> <br />  </Target> <br /></Project></p> </blockquote> <p><strong>b.proj</strong></p> <blockquote> <p><Project DefaultTargets="Test" xmlns="<a href="http://schemas.microsoft.com/developer/msbuild/2003"">http://schemas.microsoft.com/developer/msbuild/2003"</a> ToolsVersion="3.5"> <br />  <Target Name="Test"> <br />    <Message Importance="High" Text="Foo=$(Foo)" /> <br />  </Target>  <br /></Project></p> </blockquote> <p>Then when you run <em>%SystemRoot%\Microsoft.NET\Framework\v3.5\MSBuild.exe a.proj</em>, it should print out: <em>Foo=123</em>.  Woot!</p> <p>We have successfully passed some properties to a recursive invocation of MSBuild.</p> <h4>ToolsVersion is Essential</h4> <p>Now what happens if you omit <em>ToolsVersion="3.5"</em>.</p> <p>Well, it you omit it from <strong>b.proj</strong> then the script will still work.</p> <p>But it you omit it from <strong>a.proj</strong> MSBuild will run in a v2.0 compatibility mode.  So the value of the <em>Foo</em> property will NOT be passed into <strong>b.proj</strong>.  Not too surprising but it took me a little while to track it down.</p> <p>This just goes to show how important the <em>ToolsVersion </em>attribute is.  Be careful!</p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-43127089406889066482008-05-16T13:25:00.001-07:002008-05-16T13:25:42.676-07:00Announcing Gallio v3.0 Alpha 3 Update 1<p>In my <a href="http://blog.bits-in-motion.com/2008/05/mbunit-testfixture-attribute-is-now.html">previous post</a>, I mentioned that MbUnit v3's <strong>TestFixture</strong> attribute is now optional.  I have also fixed a couple of minor bugs.</p> <p>Download Alpha 3 Update 1: <a href="http://www.gallio.org/files/GallioBundle-3.0.0.251-Setup.exe">GallioBundle-3.0.0.251-Setup.exe</a></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3a26dc4f-5fb4-4f18-a9f7-e727900a3f69" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-68715475261291952942008-05-15T13:57:00.001-07:002008-05-15T13:58:49.609-07:00MbUnit TestFixture Attribute is Now Optional<p>Historically, MbUnit has used a custom attribute called <strong>TestFixture</strong> to indicate that a class contains tests.</p> <p>This isn't the only such attribute.  Other custom attributes, such as <strong>AssemblyFixture</strong> in MbUnit v3, denote various special kinds of fixtures.  However, <strong>TestFixture</strong> is the standard and most frequently used kind of fixture.</p> <p>When James Newkirk and Brad Wilson designed xUnit.Net they omitted several features that they felt were redundant, confusing, or harmful.  <strong>TestFixture</strong>, long a staple of unit testing frameworks in .Net was one such piece of syntax that was axed: it was simply redundant.  A class is obviously a test fixture if it is not abstract and it contains suitably annotated test methods.</p> <p>In a <a href="http://blog.bits-in-motion.com/2008/03/do-we-need-testfixture-anymore.html">previous post</a> I asked whether people felt that MbUnit should follow suit with xUnit.Net and either drop <strong>TestFixture</strong> altogether or make it optional.  The general sentiment seems to have fallen in the latter category.</p> <p>So effective now, in MbUnit v3, <strong>TestFixture</strong> is optional.  I will publish an update to Gallio Alpha 3 with this enhancement shortly.</p> <h3>Examples</h3> <h4>1. Simple fixture in C#.</h4> <blockquote> <p>public class SimpleFixture <br />{ <br />    [Test] <br />    public void SimpleTest() <br />    { <br />        Assert.AreEqual(4, 2 + 2); <br />    } <br />}</p> </blockquote> <h4>2. Simple fixture in F#.</h4> <blockquote> <p>#light <br />using MbUnit.Framework <br /> <br />[<Test>] <br />let SimpleTest() = Assert.AreEqual(4, 2 + 2)</p> </blockquote> <h4>3. Data-driven fixture in C# using generic type parameters.</h4> <blockquote> <p>[Row(typeof(List<int>), typeof(int))] <br />[Row(typeof(Dictionary<string, int>), typeof(KeyValuePair<string, int>))] <br />public class DataDrivenFixture<T, S> where T : ICollection<S>, new() <br />{ <br />    [Test] <br />    public void CountIsIncrementedWhenOneItemIsAdded() <br />    { <br />        T collection = new T(); <br />        collection.Add(default(S)); <br />        Assert.AreEqual(1, collection.Count); <br />    } <br />}</p> </blockquote> <h4>4. A different data-driven fixture in C# using a constructor.</h4> <blockquote> <p>public class HomestarRunnerProductTest <br />{ <br />    private string productName; <br />    private Product product; <br /> <br />    [Row("Fluffy Puff Marshmallows")] <br />    [Row("Cheat Command O's")] <br />    public Fixture(string productName) <br />    { <br />        this.productName= productName; <br />    } <br /> <br />    [SetUp] <br />    public void BuyProduct() <br />    { <br />        product = Store.BuyProduct(productName); <br />    } <br /> <br />    [TearDown] <br />    public void ReturnProduct() <br />    { <br />        Store.ReturnProduct(product); <br />    } <br /> <br />    [Test] <br />    public void ShouldComeInAShinyBox() <br />    { <br />        Assert.IsTrue(product.HasShinyBox); <br />    } <br /> <br />    [Test] <br />    public void ShouldTasteSweet() <br />    { <br />        Assert.AreEqual(Flavor.Sweet, product.Flavor); <br />    } <br />}</p> </blockquote> <h4>5. Another data-driven fixture in C# using fields.</h4> <blockquote> <p>public class DataDrivenFixture <br />{ <br />    [Column(OS.Windows, OS.Mac, OS.Linux)] <br />    public OS os; <br /> <br />    [Column(100, 1000, 10000)] <br />    public int dataSetSize; <br /> <br />    public void TestConfiguration() <br />    { <br />        // ... do something with <em>os</em> and <em>dataSetSize</em> <br />    } <br />}</p> </blockquote> <h4>6. A fixture represented as a static class with static test methods in C#.</h4> <blockquote> <p>public static class StatelessFixture <br />{ <br />    [Test] <br />    public static void StatelessTest() <br />    { <br />        Assert.AreEqual(4, 2+ 2); <br />    } <br />}</p> </blockquote> <h4>7. A data-driven fixture in F# using a constructor.  (hypothetical)</h4> <p>I was going to demo something similar using F# but I couldn't get it to compile an attribute with object[] parameters.</p> <p>I tried a bunch of variations but the only thing I could get to compile properly was a Row with an empty array.  Other attempts variously spit out errors like <em>"error FS0191: invalid custom attribute value (not a constant): Format`5.ctor.1@[obj, obj, obj, obj, unit]`"2". "</em></p> <p>Looks like there are bugs in the F# compiler as it does not seem to support array creation or type expressions as valid attribute values.</p> <blockquote> <p>#light <br />using MbUnit.Framework <br /> <br />[<Row( [| 123, "123" |] )>]             <font color="#ff0000"><--- does not compile in F# 1.9.4.</font> <br />type when_string_formatter_receives_an_integer = { value : int, formattedResult : string } with <br />    [<Test>] <br />    member f.it_should_format_the_value_as_a_string() = Assert.AreEqual(f.formattedResult, StringFormatter.Format(f.value)); <br />end</p> </blockquote> <h3>Final Remarks</h3> <p>The above examples only just scratch the surface of the supported variations.  Really, you can pick and choose the style you wish to use in your tests as you like.</p> <p><em>P.S. I also fixed the bug that prevented Jim Burger from using MbUnit effectively with F#.  (<a href="http://www.nervoustych.com/blog/PermaLink,guid,fc3a3974-2284-43e1-a58e-f8a6af4cca4d.aspx">more details</a>)</em></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:de8f905f-5c5a-49bb-a7fe-0927c407a6bc" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-18163548636999389082008-05-13T02:49:00.001-07:002008-05-13T18:41:59.796-07:00Announcing Gallio v3.0 Alpha 3<p>Today we have released Gallio v3.0 Alpha 3, including a preview of MbUnit v3.  <a href="http://lh6.ggpht.com/jeff.brown/SClj_2_903I/AAAAAAAAAG4/vIX9gWFCvSk/Gallio%20Leaf%5B9%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="141" alt="Gallio Leaf" src="http://lh3.ggpht.com/jeff.brown/SClkAG_904I/AAAAAAAAAHA/HafkTwQ3rjs/Gallio%20Leaf_thumb%5B5%5D.png?imgmax=800" width="138" align="right" border="0" /></a> </p> <p>The installer is available here: <a href="http://www.gallio.org/files/GallioBundle-3.0.0.247-Setup.exe">GallioBundle-3.0.0.247-Setup.exe</a> (temporary link)</p> <p>It will also be available from the Gallio website shortly: <a href="http://www.gallio.org">www.gallio.org</a>.</p> <p>There has been quite a lot of progress in this release including new features, bug fixes, and various internal changes to make it easier for runner and framework authors to build new cool stuff on top of Gallio.</p> <p>Here is a quick summary of these changes.</p> <h2>New and Notable</h2> <h3>New Features</h3> <h4></h4> <h4>1. Annotations</h4> <p>Annotations are a means for test frameworks to communicate errors, warnings and informational messages to the user in association with particular code elements.</p> <p>MbUnit v3 uses annotations to inform the user about improperly used attributes and to highlight points of interest such as ignored or pending tests.</p> <p>Annotations are displayed as messages in test reports.</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SClkAW_905I/AAAAAAAAAHI/mKZxflIPDaY/image%5B16%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="116" alt="image" src="http://lh4.ggpht.com/jeff.brown/SClkAW_906I/AAAAAAAAAHQ/uDXVXwYRuO4/image_thumb%5B8%5D.png?imgmax=800" width="451" border="0" /></a> </p> <p>They manifest as error/warning stripes in R#.</p> <p><a href="http://lh5.ggpht.com/jeff.brown/SClkAm_907I/AAAAAAAAAHY/lV1wJJ_pnIE/image%5B4%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="166" alt="image" src="http://lh5.ggpht.com/jeff.brown/SClkAm_908I/AAAAAAAAAHg/onS31STx3P4/image_thumb%5B2%5D.png?imgmax=800" width="414" border="0" /></a> </p> <p>Graham Hay has also added an <em>Annotation</em> view in the Icarus GUI.  Double-clicking on the annotation displays the source code.</p> <p><a href="http://lh6.ggpht.com/jeff.brown/SClkA2_909I/AAAAAAAAAHo/9bv1C5F8PMY/image%5B12%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="image" src="http://lh3.ggpht.com/jeff.brown/SClkBG_90-I/AAAAAAAAAHw/IQ-OYmPrC2Q/image_thumb%5B6%5D.png?imgmax=800" width="567" border="0" /></a> </p> <h4>2. Report Enhancements</h4> <p>HTML reports now include navigation stripes to provide a quick overview of the contents of the report and to navigate to failed, inconclusive and skipped tests.</p> <p>When JavaScript is enabled, test results are automatically collapsed for ease of reading.  They are automatically expanded during navigation.</p> <p><a href="http://lh3.ggpht.com/jeff.brown/SClkCG_90_I/AAAAAAAAAH4/Qg0SwQH_tHw/image%5B20%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="440" alt="image" src="http://lh4.ggpht.com/jeff.brown/SClkCW_91AI/AAAAAAAAAIA/EHll6Eve8tM/image_thumb%5B10%5D.png?imgmax=800" width="677" border="0" /></a> </p> <p>HTML reports can grow to become quite large when there are many tests.  Accordingly, we have added a "Condensed" version of this report that omits passing tests.  This is particularly useful in combination with CruiseControl.Net.</p> <p><a href="http://lh5.ggpht.com/jeff.brown/SClkCm_91BI/AAAAAAAAAII/OPAzXX2139o/image%5B28%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="309" alt="image" src="http://lh6.ggpht.com/jeff.brown/SClkC2_91CI/AAAAAAAAAIQ/cNT4IfAX7Kc/image_thumb%5B14%5D.png?imgmax=800" width="554" border="0" /></a> </p> <h4>3. Icarus Test Execution Log</h4> <p>Graham Hay has added a new <em>Execution Log </em>view to Icarus.  You can view test results here while tests execute.   If you periodically refresh the view then you can watch test execution in near real-time including output from long-running tests that are still in flight.</p> <p> <a href="http://lh4.ggpht.com/jeff.brown/SClkDW_91DI/AAAAAAAAAIY/PkCeuuI9Uh4/image%5B32%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="366" alt="image" src="http://lh5.ggpht.com/jeff.brown/SClkDm_91EI/AAAAAAAAAIg/b9Ckqh4oDx0/image_thumb%5B16%5D.png?imgmax=800" width="566" border="0" /></a> </p> <h4>4. Test Assembly Configuration Files</h4> <p>Gallio now provides all of the machinery required to support test assembly configuration files.  All frameworks and adapters can benefit from this support, including MbUnit v3.  Just create a configuration file named: "MyTestAssembly.dll.config" and put it next to your test assembly (assuming it is called MyTestAssembly).</p> <h4>5. MSTest Adapter</h4> <p>Julian Hidalgo implemented an adapter for MSTest.  This feature enables all Gallio runners to run MSTest tests.  One of the interesting consequences of this design is that R# v3.1 is now capable of viewing and running MSTest tests via Gallio.</p> <p><a href="http://lh5.ggpht.com/jeff.brown/SClkDm_91FI/AAAAAAAAAIo/w7x_NRCRd8c/image%5B8%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="167" alt="image" src="http://lh6.ggpht.com/jeff.brown/SClkD2_91GI/AAAAAAAAAIw/kF0g9upY8No/image_thumb%5B4%5D.png?imgmax=800" width="319" border="0" /></a> </p> <h4>6. Visual Studio Team System Integration (Experimental)</h4> <p>Gallio now includes an experimental <strong>ITip</strong> provider for integration with Visual Studio Team System 2008.</p> <p>To use it, be sure to select the feature in the Gallio Installer.  It is currently excluded from installation by default because of its experimental nature.</p> <p>Then just load up your favorite test project in Visual Studio 2008 and run a Build.  The tests should now appear in the Visual Studio <strong>Test View</strong>.  You can then run them from there.  It should work with all supported test frameworks.</p> <p><a href="http://lh6.ggpht.com/jeff.brown/SCln62_91HI/AAAAAAAAAI4/JhM4F3u1WAY/image%5B36%5D.png?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="295" alt="image" src="http://lh4.ggpht.com/jeff.brown/SCln7W_91II/AAAAAAAAAJA/oGCEu_Idfbw/image_thumb%5B18%5D.png?imgmax=800" width="341" border="0" /></a> </p> <p>As far as I know, we are the first Open Source testing project to provide this kind of integration.</p> <p>If would like to contribute to the development of this feature please let me know!</p> <h4>7. Test Runner Extensions</h4> <p>Many new features can be added to Gallio by implementing plug-ins.  However, some users have requested the ability to extend test runners to change how test results are reported.</p> <p>Gallio Alpha 2 included an <strong>ITestMonitor</strong> interface that roughly served this purposes by making it possible to inject additional behavior into the test runner's event handlers.  In Gallio Alpha 3, we have introduced the <strong>ITestRunnerExtension</strong> interface and provided a mechanism for loading extensions into the runners by means of an additional argument.</p> <p>Implementing a test runner extension is straightforward:</p> <ol> <li>Create a new assembly for your extension. </li> <li>Add a reference to Gallio.dll. </li> <li>Create a subclass of <strong>TestRunnerExtension</strong>. </li> <li>In the <strong>Initialize</strong> method, register event handlers on the <strong>Events</strong> object provided to the extension. </li> <li>Build your assembly. </li> <li>Copy the file wherever you like. </li> </ol> <p>Using a test runner extension is similar to registering an MSBuild logger.</p> <ul> <li>If you are using Gallio.Echo.exe (the command-line test runner), add an argument like: "/extension:MyFancyExtension,MyFancyExtension.dll". </li> <li>If you are using the Gallio NAnt or MSBuild tasks, the process is similar.  Refer to the documentation of these tasks for details. </li> <li>There is a built-in extension for debugging.  Add "/extension:DebugExtension,Gallio" or an equivalent argument to enable it.  Be sure to also set the message verbosity to Debug. </li> </ul> <p>The plan is to open up more of the platform to lightweight extensions of this sort.</p> <h4>8. Parameterized Test Enhancements</h4> <p>MbUnit v3 now fully supports generic test fixtures and test methods and various other parameterizations.</p> <p>A test can now be parameterized in any of the following ways:</p> <ul> <li>Adding a method parameter to a test method. </li> <li>Adding a generic method parameter to a test method. </li> <li>Adding a constructor parameter to a test fixture. </li> <li>Adding a field to a test fixture. </li> <li>Adding a writable property to a test fixture. </li> <li>Adding a generic type parameter to a test fixture. </li> </ul> <p>Correspondingly data-source attributes can be specified on any of the following code elements:</p> <ul> <li>Test methods. </li> <li>Test method parameters. </li> <li>Test method generic parameters. </li> <li>Test fixture types. </li> <li>Test fixture constructors. </li> <li>Test fixture constructor parameters. </li> <li>Test fixture fields. </li> <li>Test fixture properties. </li> <li>Test fixture generic parameters. </li> </ul> <p>So there are many choices, but each choice is quite simple.</p> <p>Here are a few interesting combinations.</p> <h5>A basic "Row"-test. </h5> <p><em>Note: The [RowTest] attribute is not needed anymore and has been eliminated.</em></p> <h5></h5> <blockquote> <p>[TestFixture] <br />public class Fixture <br />{ <br />    [Test] <br />    [Row(3, 4, 5, true)] <br />    [Row(1, 2, 3, false)] <br />    public void Test(int a, int b, int c, bool expectedResult) <br />    { <br />        Assert.AreEqual(expectedResult, Math.IsPythagoreanTriple(a, b, c)); <br />    } <br />}</p> </blockquote> <h5>A generic "Type"-test.</h5> <p><em>Note: The [TypeFixture] attribute is not needed anymore and has been eliminated.</em></p> <blockquote> <p>[TestFixture] <br />[Row(typeof(List<int>))] <br />[Row(typeof(LinkedList<int>))] <br />public class Fixture<T> where T : IList<int>, new() <br />{ <br />    [Test] <br />    public void Test() <br />    { <br />        T list = new T(); <br />        list.Add(123); <br />        Assert.AreEqual(1, list.Count); <br />    } <br />}</p> </blockquote> <h5>A combinatorial test.</h5> <p><em>Note: The [CombinatorialTest] attribute is not needed anymore and has been eliminated.</em></p> <blockquote> <p>[Test] <br />public void Test([Column(0, 1)] int a, [Column("a", "b")] string b, [Column(false, true)] bool c) <br />{ <br />    // Test something with the specified combination. <br />    // Will be executed 8 times total. <br />}</p> </blockquote> <h5>A pairwise test.</h5> <p>Only tests all combinations of pairs of values.  Can yield a significant reduction in test cases compared to ordinary combinatorial tests while still obtaining great coverage.  See also: <a href="http://www.pairwise.org">www.pairwise.org</a>.</p> <blockquote> <p>[Test, PairwiseJoin] <br />public void Test([Column(0, 1)] int a, [Column("a", "b")] string b, [Column(false, true)] bool c) <br />{ <br />    // Test something with the specified combination. <br />    // Will be executed only 4 times instead of 8. <br />}</p> </blockquote> <h5>A CSV data source.</h5> <p>Just one of many external data sources to be implemented.</p> <blockquote> <p>[Test] <br />[CsvData(ResourcePath="CsvDataTest.csv", HasHeader=true)] <br />public void ImplicitlyScopedResourceWithHeader(decimal price, string item) <br />{ <br />    Log.WriteLine("{0}: {1}", item, price); <br />} </p> </blockquote> <p>The data itself should be stored in an embedded resource called "CsvDataTest.csv".  We just create a file with that name in the same folder as the test class and then set its <em>Build Action </em>property to <em>Embedded Resource</em> in Visual Studio.</p> <blockquote> <p>Item, Price <br />Apples, 1.00 <br />Bananas, 1.50 <br />Cookies, 2.00</p> </blockquote> <h5>Automatic data type conversions.</h5> <p>Can automatically convert strings into <strong>DateTime</strong>s and <strong>double</strong>s into <strong>decimal</strong>s for example.</p> <h3>Architecture Improvements</h3> <p>There were a number of internal architecture improvements in Gallio Alpha 3.  Here's a quick summary.</p> <h4></h4> <h4>1. Unified Hosting Apparatus</h4> <p>In Gallio Alpha 2 there was some duplication between the responsibilities of the <strong>IHost</strong> and <strong>ITestDomain</strong> components.  These abstractions have been refactored.  As a result, <strong>ITestDomain</strong> was replaced by <strong>ITestDriver</strong> to handle the specific needs of setting up a testing environment.</p> <p>The <strong>IHost</strong> abstraction provides a mechanism for Gallio to run code remotely such as in an isolated AppDomain or another process.</p> <h4>2. Pattern Test Framework Refactoring</h4> <p>There was an important piece missing from the data binding story in Alpha 2 that prevented certain kinds of parameterized tests from being expressed.  This has been resolved by refactoring of the Pattern Test Framework (from which MbUnit v3 is derived) and introducing the concept of a test data context.  <strong>IPattern</strong> is significantly simpler now.</p> <p>This work also prompted the introduction of the Annotations mechanism  when it became clear that we needed a much more direct mechanism for reporting semantic errors in a test to the user.</p> <h4>3. Reflection Policy Enhancements</h4> <p>Introduced the concept of a typed <strong>ConstantValue</strong> for performing reflection over unevaluated attribute values.  For example, when populating tests for the ReSharper add-in we may encounter attribute values that are of type <strong>Type</strong>.  It's quite possible for those types to not be loaded in the runtime (since we're performing reflection against an in-memory code model).  So instead we can obtain a <strong>ConstantValue</strong> that represents the <strong>Type</strong> without actually loading it.</p> <p>Gallio Alpha 3 also includes a Cecil-based reflection policy for scanning disk-based assemblies without loading them into the runtime.  The Visual Studio Team System add-in uses this policy to perform reflection without locking assemblies or introducing memory leaks.</p> <h4>4. Test Runner Redesign</h4> <p>The <strong>ITestRunner</strong> interface has been completely redesigned to make it easier to use and more versatile.  For one, the reporting functionality has now been integrated somewhat more tightly into the runner itself.  An <strong>ITestRunnerExtension</strong> can register new behaviors on a test runner using the <strong>ITestRunnerEvents</strong> interface.</p> <h4>5. Aggregate Test Drivers</h4> <p>Supporting test assembly configuration files is not as easy as it sounds.  For one, it requires us to create a separate AppDomain for each test assembly.  Then we have to somehow merge the test model and results.</p> <p>Gallio Alpha 3 introduces an aggregate test driver to help with this.  However, the current design is still somewhat in flux.  I'd appreciate some feedback on how we can improve and simplify the test framework integration story overall.</p> <h3>Bugs Fixed</h3> <h4></h4> <p>Here are a few of the bugs from Alpha 2 that have been fixed:</p> <ul> <li>Icarus now unloads assemblies promptly to avoid locking them.  You can also enable shadow-copy mode for improved efficiency. </li> <li>MbUnit v2 version compatibility problems fixed.  Should work with any version of MbUnit v2.4+. </li> <li>Hung Gallio.Host.exe processes are no more. </li> <li>xUnit.Net adapter has been upgraded to v1.0 RTM. </li> <li>Installer PATH variable corruption. </li> <li>Castle dependencies have been internalized to avoid version mismatches. </li> <li>Default thread apartment state is STA and can be overridden with the [ApartmentState] attribute. </li> <li>[Explicit] tests are now silent and do not display any output in reports unless explicitly selected, not even a message to say they are being skipped.  If you want noisy output, use [Ignore], [Pending] or [Annotation] instead. </li> </ul> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:750c909a-c62c-4a14-9a35-4cf659e52429" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-81245840264362505502008-05-12T23:16:00.001-07:002008-05-12T23:39:00.732-07:00Openings at Ingenio<div><a href="http://lh6.ggpht.com/jeff.brown/SCk2D2_901I/AAAAAAAAAGo/CEN6oTjCIXE/ggbridge%5B6%5D.jpg?imgmax=800"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="164" alt="ggbridge" src="http://lh3.ggpht.com/jeff.brown/SCk2EG_902I/AAAAAAAAAGw/kaF49DdqpHs/ggbridge_thumb%5B4%5D.jpg?imgmax=800" width="244" align="right" border="0" /></a> <p>We're hiring!  Want to work with me?</p> <p>To learn more or to apply, send an email with your résumé to <em><a href="mailto:jobs@ingenio.com">jobs@ingenio.com</a></em>.</p> <p>Also check out <a href="http://www.ingenio.com/documents/corp/company/employment.asp">this link</a> for more opportunities at Ingenio.</p> </div> <h4>Platform Toolsmith</h4> <p>Do you love building tools?  Do you get a kick out of building integrated systems that just work?</p> <p>Ingenio is looking for someone to help build a robust and highly integrated platform for software development, deployment and testing.   Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to assemble these pieces and to verify that they work together correctly to provide a compelling user experience.</p> <p>We need an experienced toolsmith who understands the challenge of release engineering, system monitoring, infrastructure build-out and software architecture to help us keep our coders coding, our testers testing, our users using, and our systems running smoothly.</p> <p>Sample projects:</p> <ul> <li>Build new plug-ins for our distributed system monitoring application. </li> <li>Develop a new deployment tool for coordinating updates to our server farm. </li> <li>Implement a SIP phone emulator for testing telephony applications. </li> <li>Plan SOA and ESB middleware deployment projects. </li> <li>Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN. </li> </ul> <p>What we will look for in you:</p> <ul> <li>You love to program! </li> <li>You like to tinker and take things apart... and put them back together better than they were before. </li> <li>You have great communication skills. </li> <li>You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++. </li> <li>You have experience with release engineering and deployments. </li> <li>You have a 4 year degree in computer science or engineering. </li> </ul> <p>Location: San Francisco, CA.  Downtown with easy access to BART and Muni.</p> <h4>Test Automation Guru (Lead)</h4> <p>Do you love testing?  Do you love working with testers, teaching them new tricks, designing systems and building tools?</p> <p>Ingenio is looking for someone to lead our test automation effort.</p> <p>Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  There are many challenges involved in the construction of controlled test environments that can obtain reliable results and find bugs.  We need an experienced lead who thoroughly groks testing and can help us take test automation to the next level.</p> <p>Sample projects:</p> <ul> <li>Design a virtual automation test environment. </li> <li>Build test tools and monitoring infrastructure. </li> <li>Implement model-based and automated exploratory testing approaches. </li> <li>Plan comprehensive automation test projects. </li> <li>Mentor junior members of the test automation team. </li> <li>Hire more smart people to work with. </li> <li>Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN. </li> </ul> <p>What we will look for in you:</p> <ul> <li>You have experience leading, teaching and motivating others to excellence. </li> <li>You have a strong programming background. </li> <li>You have great communication skills. </li> <li>You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++. </li> <li>You are familiar with at least one xUnit testing tool such as MbUnit, NUnit or JUnit. </li> <li>You grok test automation. </li> </ul> <p>Location: San Francisco, CA.  Downtown with easy access to BART and Muni.</p> <h4>Test Automation Wizard</h4> <p>Do you love programming <em>and</em> testing?  Do you enjoy writing high-quality code using the latest tools?  Do you hate bugs?  Do you like solving challenging system integration problems?</p> <p>Ingenio is looking for test automation engineers to develop a comprehensive and maintainable test suite for our products.</p> <p>Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  We need talented tester/developers and developer/testers to decide what to test, to write tests and to adopt novel testing strategies.</p> <p>Sample projects:</p> <ul> <li>Write automated tests for our system using C#. </li> <li>Implement model-based and automated exploratory testing approaches. </li> <li>Build infrastructure for deploying, running and monitoring tests. </li> <li>Plan comprehensive automation test projects. </li> <li>Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN. </li> </ul> <p>What we will look for in you:</p> <ul> <li>You love to program! </li> <li>You are smart, passionate, eager to learn and get things done. </li> <li>You have great communication skills. </li> <li>You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++. </li> <li>You are familiar with at least one xUnit testing tool such as MbUnit, NUnit or JUnit. </li> <li>You have prior experience writing automated tests. </li> </ul> <p>Location: San Francisco, CA.  Downtown with easy access to BART and Muni.</p> <h4>Test Automation Apprentice (Intern)</h4> <p>Do you enjoy programming?  Are you curious about test automation?  Do you want to get a head start in the industry?</p> <p>Ingenio is looking for smart students to bring in fresh ideas, challenge the established order and remind us all to have fun.</p> <p>Our system consists of a mixture of web, telephony and data platforms so it takes a lot of ingenuity to test that these pieces work together correctly to provide a compelling user experience.  As part of that effort, we officially sponsor the development of MbUnit, an Open Source testing framework.  We are constantly searching for ways to improve our processes.</p> <p>We hope to learn as much from you as we promise to teach you.</p> <p>Sample projects:</p> <ul> <li>Create something new and fantastic that we haven't thought of yet in this list... </li> <li>Develop a tool to automatically spider our web sites using C# and find bugs. </li> <li>Write automated tests for our system using C#. </li> <li>Build infrastructure for deploying, running and monitoring tests. </li> <li>Create test reports. </li> <li>Work on Open Source projects such as Gallio, MbUnit, Archimedes and WatiN. </li> </ul> <p>What we will look for in you:</p> <ul> <li>You love to program! </li> <li>You are smart, passionate, eager to learn and get things done. </li> <li>You have great communication skills. </li> <li>You know at least one object-oriented programming language such as C#, Java, Python, Ruby or C++. </li> <li>You are currently enrolled or have recently graduated from an accredited university. </li> </ul> <p>Location: San Francisco, CA.  Downtown with easy access to BART and Muni.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:148d35cd-abb9-4b86-a9db-d4bb5886661e" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/jobs" rel="tag">jobs</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-80273169908268392312008-05-12T00:00:00.001-07:002008-05-12T00:00:42.598-07:00Google Code Download WTF<p>I was getting ready to publish Gallio Alpha 3 tonight but we're out of space on Google Code.</p> <p>Ok, no problem... I'll just delete some stuff.</p> <p>Google Code had other ideas:</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SCfrF2_90zI/AAAAAAAAAGY/lB-LEf5oUCE/image%5B5%5D.png?imgmax=800"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="125" alt="image" src="http://lh6.ggpht.com/jeff.brown/SCfrGW_900I/AAAAAAAAAGg/2ouis4KVAus/image_thumb%5B3%5D.png?imgmax=800" width="644" border="0" /></a></p> <p>Uhh... But I don't need this version anymore: I've archived it myself and I need the free space right now!</p> <p>Meanwhile my request for more quota is still pending...</p> <p><em>(I'm just glad I never wrote a script to upload nighty builds.)</em></p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-46443103141504805502008-05-04T22:22:00.001-07:002008-05-04T23:37:49.363-07:00Another Programmer Bites the Dust<p>I've been struggling with Carpal Tunnel Syndrome for 6 or 8 months now.</p> <p>I don't quite remember when it started.  I've had bouts of muscle tension on and off throughout my life.  After all, I've pretty much spent every other waking hour in front of a computer for the last 18 years or so (total of 22 years programming but during my early years I did not have a computer at home).  But recently I started noticing different symptoms.</p> <ol> <li>Numbness and tingling are now commonplace occurrences. </li> <li>It does not go away after a night's rest. </li> <li>It does not go away after a day or two of not using the computer. </li> <li>It has invaded other aspects of my life including cooking, recreation, sleep and sex. </li> <li>I find myself searching for ways to <em>work differently</em> and to avoid sustained typing or mousing. </li> <li>I find myself wishing for an eye-tracker and decent voice recognition to help out around the edges. </li> <li>It's made me cry... </li> </ol> <p>I have already made many adjustments to my ergonomics and home life style.</p> <ol> <li>I use a keyboard tray tilted at a negative angle. </li> <li>I use a Microsoft Natural Wireless Ergonomic Keyboard and Mouse combo. </li> <li>I wear elbow braces during the day. </li> <li>I wear write braces during the night. </li> <li>I try to sit properly. </li> <li>My wife opens jars for me. </li> </ol> <p><em>But it's still getting worse.</em></p> <p>Today I installed <a href="http://www.workrave.org/">Workrave</a> to help remind me to take breaks, do my exercises and quit after working a long day.</p> <p><em>*sigh*</em></p> <h4>Flip Side</h4> <p>I am now taking more active leadership roles.  I am a Lead Software Engineer at the office and the MbUnit / Gallio Lead on the side.  </p> <p>There's just so much cool stuff to build out there!  And I know all sorts of smart people that I can set to the task of building it.  :-)</p> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-38595503630973128622008-05-02T03:11:00.001-07:002008-05-02T04:49:32.873-07:00A Good Test Finds Bugs<p>This evening I found myself thinking about what my favourite test in Gallio must be.</p> <p>It could be the formatter tests that are simple and to the point and leverage many of the good traits of the MbUnit Row-test, including generic method parameters.</p> <p>It could be the MbUnit integration tests that self-host Gallio within itself to run tests and carefully analyze their output.</p> <p><em>Nahh...</em></p> <p>My favourite Gallio test is the abstract reflection policy <strong>exhaustive test suite</strong>!  It's not pure.  It's not pretty.  It's not tightly focused.  It's not short.  It's not precise.  It's not self contained  (it uses native .Net reflection as an oracle).  But boy does it find bugs!  All sorts of obscure deviations from expected behaviour in each of the 4 current reflection policy implementations.</p> <p><em>It's an awful test but it does what a test should do: it finds bugs...</em></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:fa3b539c-6d7b-442a-b7ae-e1b0655b59e8" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-48173250328083796392008-04-29T04:17:00.001-07:002008-04-29T04:17:25.454-07:00Death By a Thousand Cuts<p>It feels like I'll never get this release out.</p> <p>I'm currently facing an interesting flavour of DLL hell (tastes like bananas) resulting from copy-local assemblies that get loaded into the same application (Visual Studio) in different load contexts.  Basically, ReSharper and Visual Studio Team Test both want to load Gallio.dll but they do it in different ways from different locations.  This results in some rather curious behavior because two identical copies of the assembly will be loaded but they are nevertheless considered different from one another.</p> <p>It would be nice if we could just tell ReSharper and Visual Studio Team Test to load my add-in assemblies from the Gallio installation path, but neither of them actually support that behavior.  They both require their add-ins to be copied into very specific folders.</p> <p>I can think of two possible fixes right now:</p> <ol> <li>Add some hacks to install a custom assembly resolver just in time at all entry points into the add-ins so that we can control more precisely how Gallio.dll gets loaded.  That way we can avoid having multiple copies of Gallio.dll.</li> <li>Put Gallio.dll into the GAC.</li> </ol> <p>I previously used option #1 for the Gallio ReSharper add-in.  It was a real pain because I had to carefully instrument all entry points into the add-in and avoid referencing any Gallio types until the assembly resolver hook was installed.  I ripped this brittle code out a couple of weeks ago since I figured just copying Gallio.dll locally would be good enough.  <em>(guess again!)</em></p> <p>So option #2 really seems best.  Keep in mind that the copy of Gallio in the GAC should only be used for external tools integration.  I don't anticipate test assemblies or the basic standalone runner actually referring to anything in the GAC so Gallio should still be usable in-place without requiring any installation steps (except for these add-ins of course).</p> <p>However, it's 4am now so I'm going to sleep on it for a little while.  It may be that using the GAC will cause more headaches such as problems with the NAnt or MSBuild tasks that might also involve a little non-standard assembly resolver-foo of their own.</p> <p> </p> <p>Next problem: Throw out NSIS (finally!) and rewrite the installer using WiX...</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4b3b095c-5cc8-4934-9884-21aa2d4ad664" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-59193779486009972692008-04-28T14:12:00.001-07:002008-04-28T14:17:25.072-07:00The C# Null-Coalescing Operator, PEVerify and ILMerge<p>It seems I errantly blamed ILMerge for those PEVerify errors. At worst it may be a C# compiler optimization gone awry or it may be that PEVerify is not smart enough.</p> <h4>The Source</h4> <p>Consider this code:</p> <p><code>public IList<ITestCommand> Children <br></code><code>{ <br> get { return children ?? (IList<ITestCommand>)EmptyArray<ITestCommand>.Instance; } <br>}</code></p> <p>The left-hand side of the null-coalescing operator has type: <strong>List<ITestCommand></strong>.</p> <p>The right-hand side of the null-coalescing operator has type: <strong>ITestCommand[] </strong>before the cast.</p> <p>The result has type: <strong>IList<ITestCommand></strong>.</p> <p>So we need a little silent cast in there to make the types match up on either side. Really, it's just providing a compatible upper bound to which both sides can be converted. At runtime, this operation is a no-op. Technically it's something that the compiler itself could have inferred if it were smart enough.</p> <h4></h4> <h4>The Unoptimized IL</h4> <p>Let's take a quick look at the IL that the C# compiler generates for a standard unoptimized build. </p> <p>Notice that the <strong>castclass</strong> operator appears in the listing. There is also quite a bit of jiggery-pokery involving a compiler generated temporary local variable.</p><pre>.method public hidebysig specialname newslot virtual final instance class [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.IList<>">System.Collections.Generic.IList`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>> <b><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand/get_Children():System.Collections.Generic.IList<Gallio.Model.Execution.ITestCommand>">get_Children</a></b>() cil managed
{
.maxstack 2
.locals init (
[0] class [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.IList<>">System.Collections.Generic.IList`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>> <b>CS$1$0000</b>)
L_0000: <a>nop</a>
L_0001: <a>ldarg.0</a>
L_0002: <a>ldfld</a> class [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.List<>">System.Collections.Generic.List`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>> <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand">Gallio.Model.Execution.ManagedTestCommand</a>::<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand/children:System.Collections.Generic.List<Gallio.Model.Execution.ITestCommand>">children</a>
L_0007: <a>dup</a>
L_0008: <a>brtrue.s</a> L_0015
L_000a: <a>pop</a>
L_000b: <a>ldsfld</a> !0[] <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Collections.EmptyArray<>">Gallio.Collections.EmptyArray`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>>::<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Collections.EmptyArray<Gallio.Model.Execution.ITestCommand>/Instance:<!0>%5b%5d">Instance</a>
L_0010: <a>castclass</a> [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.IList<>">System.Collections.Generic.IList`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>>
L_0015: <a>stloc.0</a>
L_0016: <a>br.s</a> L_0018
L_0018: <a>ldloc.0</a>
L_0019: <a>ret</a>
}</pre>
<h4>The Optimized IL</h4>
<p>When generating optimized code, the C# compiler realizes that the <strong>castclass</strong> is unnecessary. So it drops it. It also drops the unnecessary load/stores to a local variable and we end up with the following code.</p><pre></pre><font face="Courier New"></font><pre>.method public hidebysig specialname newslot virtual final instance class [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.IList<>">System.Collections.Generic.IList`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>> <b><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand/get_Children():System.Collections.Generic.IList<Gallio.Model.Execution.ITestCommand>">get_Children</a></b>() cil managed
{
.maxstack 8
L_0000: <a>ldarg.0</a>
L_0001: <a>ldfld</a> class [<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089">mscorlib</a>]<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Collections.Generic.List<>">System.Collections.Generic.List`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>> <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand">Gallio.Model.Execution.ManagedTestCommand</a>::<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ManagedTestCommand/children:System.Collections.Generic.List<Gallio.Model.Execution.ITestCommand>">children</a>
L_0006: <a>dup</a>
L_0007: <a>brtrue.s</a> L_000f
L_0009: <a>pop</a>
L_000a: <a>ldsfld</a> !0[] <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Collections.EmptyArray<>">Gallio.Collections.EmptyArray`1</a><class <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Model.Execution.ITestCommand">Gallio.Model.Execution.ITestCommand</a>>::<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://Gallio::eb9cfa67ee6ab36e/Gallio.Collections.EmptyArray<Gallio.Model.Execution.ITestCommand>/Instance:<!0>%5b%5d">Instance</a>
L_000f: <a>ret</a>
}</pre>
<h4></h4><pre></pre>
<h4>PEVerify Has a Conniption</h4>
<p>Without the <strong>castclass</strong> in the optimized code, the IL is now missing a crucial piece of information: what is the type of the value of the top of the stack when we reach the <strong>ret</strong> instruction?</p>
<p>In one case, we may have duplicated the value produced by the <strong>ldfld</strong> instruction so the top has type <strong>List<ITestCommand></strong>.</p>
<p>In the other case, we have discarded the original value and instead loaded an array from somewhere else using <strong>ldsfld</strong> so the top has type <strong>ITestCommand[].</strong></p>
<p>Uh oh!</p><code>[IL]: Error: [C:\Source\MbUnit\v3\src\Gallio\Gallio\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Children][offset 0x0000000F][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack.</code>
<p>Without the <strong>castclass</strong> PEVerify has to do some rather more complicated work to figure out whether the types are compatible. Apparently, it fails. But it does get far enough to realize that one of the values can be converted to <strong>IEnumerable</strong>.</p>
<h4>Is This a Problem?</h4>
<p>I don't know. Apparently we have been running this code in Gallio release builds for many months now and not seen any <strong>InvalidProgramException</strong> errors. So even though PEVerify is confused, the CLR at least does not choke on the code.</p>
<p>In any case, it's definitely not ILMerge's fault. (Sorry Mike!)</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:83783508-8a8c-4c4b-a914-f6db55a2c02f" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/low-level" rel="tag">low-level</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-12302225157868044902008-04-28T02:28:00.001-07:002008-04-28T14:18:22.580-07:00ILMerge redux<p>In my previous post, I mentioned a problem I was having with ILMerge and how I fixed it.</p> <p>It turns out that code security attributes were not the only problem.  ILMerge is no longer complaining, but it is generating a bad output assembly just the same.  This is preventing the C# compiler from linking to the merged assembly.  Most immediately it manifested as XmlSerializers not working.</p> <p>PEVerify shows a long stream of errors: </p> <blockquote> <p>C:\Source\MbUnit\v3>"c:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\PEVerify.exe" build\target\bin\Gallio.dll </p> <p>Microsoft (R) .NET Framework PE Verifier.  Version  2.0.50727.42 <br />Copyright (c) Microsoft Corporation.  All rights reserved. </p> <p>[MD]: Error: TypeDef is marked Nested but has no enclosing type. [token:0x020004 <br />40] <br />[MD]: Warning: MemberRef has a duplicate,  token=0x0a0004f3. [token:0x0A0001AB] <br />[MD]: Warning: MemberRef has a duplicate, token=0x0a0004f4. [token:0x0A0001AC]</p> <p>... <br /></p> </blockquote> <p><em>*sigh*</em></p> <h5>More Good Fortune?</h5> <p>I upgraded ILMerge from 2.8.0202 to 2.8.0422 and now it seems to be working a little better.</p> <p>Now the TypeDef error is gone but we're still getting MemberRef warnings.  Makes me a bit nervous but at least the C# compiler is happy enough linking to the merged assembly and the XmlSerializer problem seems to be resolved.</p> <p>However, there was nothing in the change history to suggest that any bug were fixed.</p> <h5>Or Maybe Not?</h5> <p>Turns out I missed these errors:</p> <blockquote> <p>[IL]: Error: [C:\Source\MbUnit\v3\build\target\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Children][offset 0x00000012][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack. <br />[IL]: Error: [C:\Source\MbUnit\v3\build\target\bin\Gallio.dll : Gallio.Model.Execution.ManagedTestCommand::get_Dependencies][offset 0x00000012][found ref 'System.Collections.IEnumerable'][expected ref 'System.Collections.Generic.IList`1[Gallio.Model.Execution.ITestCommand]'] Unexpected type on the stack. <br />2 Errors Verifying build\target\bin\Gallio.dll</p> </blockquote> <p>Just great.  Well, I guess Gallio Alpha 3 will be delayed a little bit further while I cook up a workaround or something.</p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c0247c7f-8293-492b-a6eb-3b48ff995300" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/low-level" rel="tag">low-level</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-86660974023582638322008-04-28T01:27:00.001-07:002008-04-28T14:19:06.700-07:00Don't use self-referential Code Access Security attributes.<p>I encountered an interesting little problem today after completing a small refactoring of Gallio.  ILMerge <em>broke!</em></p> <blockquote> <p>An exception occurred during merging: <br />ILMerge.Merge: The assembly 'Gallio' was not merged in correctly. It is still listed as an external reference in the target assembly. <br />   at ILMerging.ILMerge.Merge() <br />   at ILMerging.ILMerge.Main(String[] args) </p> </blockquote> <p>True enough, the merged assembly contained a self-reference. </p> <p>The proximate cause seems to be the fact that the Gallio assembly defined a code access security attribute that it itself used.  Ordinarily these attributes should be defined in other assemblies.  Indeed, the compiler will enforce the constraint for any assembly-level permission requests.  I assume ILMerge is doing a little magic here to try to enforce similar properties.</p> <p>Ahh well.  I eliminated the custom attribute and all is well.</p> <h4>Leap of Faith</h4> <p>Julian suggested I blog about this issue because of the manner in which I resolved it.</p> <h5>Internal dialogue:</h5> <ol> <li>ILMerge is breaking because I am using it on a different assembly than I was before.  So there's something essentially wrong about this assembly or with ILMerge. </li> <li>Google turns up this error message but only in circumstances involving the ASP.Net merge tool and user error.  I don't think that's the case here. </li> <li>The documentation doesn't say anything about this. </li> <li>Renaming files around and messing with the command-line arguments doesn't change anything. </li> <li><em>Panic!</em> </li> </ol> <h5>Time passes...</h5> <ol> <li>Hmm.  When skimming the ILMerge change history to find the entry about to the addition of this error message didn't I see something about fixing security attributes?  I wonder what that was about. </li> <li>Gallio uses a custom security attribute. </li> <li>Security attributes are subject to these interesting cross-assembly reference constraints when used to declare minimum permission requests... </li> <li><em>Oh!</em> </li> </ol> <p>Now I have no idea why the mention of security attributes in the change history caught my attention, but it did.</p> <p>You might call it lateral thinking, but I'll call it sheer <em>luck!</em></p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:11f66201-6f37-4737-8d82-0c3762cba8ee" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/low-level" rel="tag">low-level</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-8718851812961332602008-04-24T19:26:00.001-07:002008-04-24T19:26:33.021-07:00Gallio integration with Visual Studio Team System<p>One of the questions I've often received about Gallio has been about whether it would integrate with MSTest and Visual Studio Team System.</p> <h3>Gallio running MSTest tests in Icarus</h3> <p>Julian did the work of writing a Gallio adapter plugin for MSTest tests.  Gallio explores MSTest tests using reflection and runs them by shelling out to MSTest.exe and parsing the test result XML file.</p> <p>Here's a screenshot of the Gallio Icarus GUI running some MSTest tests.</p> <p><a href="http://lh3.ggpht.com/jeff.brown/SBFBQ582WbI/AAAAAAAAAFQ/S_qER-0u3Jo/Alpha3-MSTestAdapterInIcarus%5B7%5D.png?imgmax=800"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="336" alt="An MSTest test running in Icarus courtesy of Gallio" src="http://lh5.ggpht.com/jeff.brown/SBFBSZ82WcI/AAAAAAAAAFY/dkwQHNTpCKA/Alpha3-MSTestAdapterInIcarus_thumb%5B3%5D.png?imgmax=800" width="604" border="0" /></a> </p> <h3>Gallio running MSTest tests in ReSharper</h3> <p>Of course, you can use any Gallio test runner to run MSTest tests.  That means you automatically get ReSharper integration too!  (And in all of the other runners too.)</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SBFBTJ82WdI/AAAAAAAAAFg/jAUylsCFMNk/Alpha3-MSTestAdapterInReSharper%5B3%5D.png?imgmax=800"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="216" alt="An MSTest test running in ReSharper courtesy of Gallio" src="http://lh5.ggpht.com/jeff.brown/SBFBUZ82WeI/AAAAAAAAAFo/jStTBIibZuY/Alpha3-MSTestAdapterInReSharper_thumb%5B1%5D.png?imgmax=800" width="604" border="0" /></a> </p> <p> </p> <h3>MSTest running Gallio tests in Visual Studio</h3> <p>Another common request has been to provide integration so that Visual Studio Team Test can run Gallio tests in the IDE and using the MSTest.exe command-line.</p> <p>This particular request was echoed to me a couple of times at ALT.Net from people who, for good or ill, have been instructed by management to use the Team System test runner instead of TestDriven.Net or ReSharper.  So I decided to give it a shot.</p> <p>Gallio Alpha 3 now includes an experimental package for Visual Studio to do just that.  (It also works on the command-line).</p> <p><a href="http://lh4.ggpht.com/jeff.brown/SBFBVJ82WfI/AAAAAAAAAFw/rE4cjt3l5FQ/Alpha3-VSTSIntegration%5B13%5D.png?imgmax=800"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="282" alt="An MbUnit test running inside of Visual Studio Team System" src="http://lh4.ggpht.com/jeff.brown/SBFBWJ82WgI/AAAAAAAAAF4/fT--pb5NIZE/Alpha3-VSTSIntegration_thumb%5B7%5D.png?imgmax=800" width="604" border="0" /></a> </p> <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7faabafa-f24c-4900-8286-e3b481eddc65" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/gallio" rel="tag">gallio</a>,<a href="http://technorati.com/tags/mbunit" rel="tag">mbunit</a></div> Jeff Brownhttp://www.blogger.com/profile/09075745057339916352noreply@blogger.comtag:blogger.com,1999:blog-9023944205100803414.post-32089043694915738222008-04-10T00:56:00.001-07:002008-04-11T11:30:05.536-07:00Gallio Archimedes<p>What do you do when you have lots of automated <em><strong>integration</strong></em> tests?</p> <p>Integration tests are different from unit tests.  They are developed by different people for different purposes with different priorities, different runtime characteristics, different maintenance overhead, different reporting needs, and different management demands.</p> <p>Unit tests should be fast, sleek and isolated.  They're the Formula 1 racers of the test world.  They whiz around the track faster than you can say Continuous Integration!</p> <p>Integration tests should be comprehensive, robust and realistic.  They're methodical and avoid taking shortcuts.  If it takes 5 minutes to simulate a particular kind of transaction then they will spend 5 minutes doing it for real.  <em>(To be fair, I'm talking about black box functional regression tests here.)</em></p> <h2></h2> <h3>The Right Tool for the Job</h3> <p>Where I work, we have lots of automated integration tests.  These are built by the QA Automation Team in C# using <a href="http://www.mbunit.com/">MbUnit</a>, <a href="http://www.gallio.org/">Gallio</a> and <a href="http://watin.sourceforge.net/">WatiN</a>.</p> <p>These tests are largely intended to displace manual QA activities for acceptance testing purposes.  Consequently they are integration tests of the highest order: they interact with the web site and other system components as nearly as real people would.  But much faster and more accurately.</p> <p>Still, they take a long time to run.  Running them interactively is completely out of the question.  Running them serially is painfully inefficient.  Running them only on demand wastes a valuable opportunity to generate Continuous Feedback from the system and to spot non-deterministic bugs.</p> <p>Moreover these tests really belong to the QA arm of our organization.  The operators are QA, Operations and Engineering staff.  The consumers are all of the above plus Program Management and other stakeholders.</p> <p>So all told, our integration testing needs are vastly different from our unit testing needs.  So we need different tools.</p> <h3>If There Is No Suitable Tool, Build It</h3> <p>For the past few months I have been thinking about building a tool to assist with deploying, running and managing automated test cases.</p> <p>There are a lot of very interesting problems to solve, particularly in the user interface and overall workflow model.  Consider that many users of the system will not be test authors themselves.  Results must be meaningful, reliable, and easy to interpret.</p> <p>Here's a sketch of what I have in mind for this new addition to the Gallio tool chain: Archimedes.</p> <p>Archimedes will incorporate:</p> <ul> <li>A distributed test runner. </li> <li>A web-based management console. </li> <li>A repository for historical test data. </li> <li>A deployment engine. </li> <li>A scheduler. </li> <li>A notification service. </li> <li>A reporting, trending and statistics module. </li> <li>A data feed and web service for mas