fitnesse.net tips and tricks gojko adzic [email protected]
TRANSCRIPT
FitNesse.NET allows you to save lots of time by writing
fixture code efficiently and by not writing fixture code when
you don’t really need it.
Simple Sample Domain
Example: define + list links
Define Links
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
List Links
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
Automatic collection wrapping
• Instead of creating your own row/array fixtures, use a flow fixture and just return an array out from a method - it gets mapped to array fixture
• Works in do/sequence flow mode
• Works on IEnumerable<T>
Automatic collection wrapping public class FlowCollections: DoFixture { private ILinkRepository repo = new MemoryLinkRepository(); public Fixture DefineLinks() { return new LinkSetupFixture(repo); } public IEnumerable<Link> ListLinks() { return repo.FindAll(); } }
System under test
• If the call does not map to anything in the fixture, flow fixtures check a “system under test”
• Set the system under test and map domain service/repository/factory calls directly to tables
• Perhaps best on Sequence fixtures
System under test public class FlowSystemUnderTest : DoFixture { private ILinkRepository repo = new MemoryLinkRepository(); public FlowSystemUnderTest() { SetSystemUnderTest(repo); } public Fixture DefineLinks() { return new LinkSetupFixture(repo); }}
System under test
info.fitnesse.FlowSystemUnderTest
Define Links
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
Find All
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
With keyword
• Set the system under test from the test page
• |with|method call|
• |with|new|class name|
• |with|new|class name|constr arg1|arg2|…|
• Use this to switch between systems under test dynamically
With Keyword
info.fitnesse.WithSystemUnderTest
with new info.fitnesse.MemoryLinkRepository
Define Links
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
Find All
Name Url
Google http://www.google.com
Yahoo http://www.yahoo.com
With Keyword
public class WithSystemUnderTest : DoFixture { public Fixture DefineLinks() { return new LinkSetupFixture((ILinkRepository) this.mySystemUnderTest); } }
Naming SUTs
• |name|foo|with|… with phrase|
• |name|bar|with|… with phrase|
• |use|foo|
• …
• |use|bar|
Naming SUTs
name google with new Link Google http://www.google.com
name yahoo with new Link Yahoo http://www.yahoo.com
use google
check valid true
use yahoo
check valid true
System under test in other fixtures
• From recently, you can use system under test for other fixtures as well!
• Eg for a column fixture as a much more flexible target object!
• Allows you to define only test-specific methods in fixtures!
Column fixture SUT
public class LinkValidityCheck:fit.ColumnFixture
{
public LinkValidityCheck()
{
SetSystemUnderTest(new Link());
}
public String comment;
}
Column fixture SUT
Link validity check
name url valid? comment
google http://www.google.com true both set, correct
blank http://www.google.com false name not set
google blank false url not set
google www.google.com false url not in correct format
Alternating system under test
• Switch SUT in runtime to load up other objects
• Use Reset() to clean up before new row
• This is a very efficient way to implement a subset fixture for huge data sets
Alternating SUT
Define Links
Name Url Id?
Google http://www.google.com >>google
Yahoo http://www.yahoo.com >>yahoo
Microsoft http://www.microsoft.com >>msft
Check Links
Id Name? Url?
<<google Google http://www.google.com
Alternating SUT
public class LinkCheckFixture : ColumnFixture{ private ILinkRepository repo; public LinkCheckFixture(ILinkRepository repo) { this.repo = repo; } public int Id { set { SetSystemUnderTest(repo.FindById(value));} }}
Automatic domain object wrapping
• Don’t use a fixture – use your domain class in the table header
• FitNesse.NET automatically creates a DoFixture and sets the system under test to a new instance of your class
Cell Handlers
• Tell FitNesse how to interpret a set of cells– Match by cell content– Match by object type
• Extend AbstractCellHandler• Load by using
Cell Handler Loader
load SavedFixtureHandler FitLibrary
load SavedFixtureHandler Fit
Example: Regexpublic class RegExHandler: AbstractCellHandler { public override bool Match(string searchString, System.Type type) { return searchString.StartsWith("/") && searchString.EndsWith("/") && typeof(string).Equals(type); } public override bool HandleEvaluate(Fixture fixture, Parse cell, Accessor accessor) { object actualValue=accessor.Get(fixture); if (actualValue == null) return false; Regex expected =new Regex(cell.Text.Substring(1,cell.Text.Length-2)); return expected.IsMatch(actualValue.ToString()); } }
Regex to the rescue
• Named SUTs can’t be used as parameters– This isn’t possible:– |name|google|with|new|…|– |save|google|
• But that would be really cool!
• So let’s implement it using a cell handler!
Saved fixture handler public class SavedFixtureHandler:AbstractCellHandler { public override bool Match(string searchString, System.Type type) { return searchString.StartsWith("\"") && searchString.EndsWith("\""); } public override void HandleInput(Fixture fixture, Parse cell, Accessor
accessor) { String innerText=cell.Text.Substring(1, cell.Text.Length-2); accessor.Set(fixture,
((FlowFixtureBase) fixture).NamedFixture(innerText)); } }
We can now use it like this!
name google with new Link Google http://www.google.com
name yahoo with new Link Yahoo http://www.yahoo.com
save "google"
save "yahoo"
find all
name url
Google http://www.google.com
Yahoo http://www.yahoo.com
info.fitnesse.MemoryLinkRepository
Suite config files
• Extract all technical information into a file
• Keep test pages nice and tidy, easily readable
• Set up with !define COMMAND_PATTERN=%m –c mySuite.config %p
• See all options on http://syterra.com/FitnesseDotNet/SuiteConfigurationFile.html
Suite config files<suiteConfig> <fit.Assemblies> <add>D:\work\netfit2\fixtures\fixtures\bin\debug\fixtures.dll</add> </fit.Assemblies> <fit.Namespaces> <add>info.fitnesse</add> </fit.Namespaces> <fit.CellHandlers> <add>info.fitnesse.SavedFixtureHandler</add> </fit.CellHandlers> <fitlibrary.CellHandlers> <add>info.fitnesse.SavedFixtureHandler</add> </fitlibrary.CellHandlers></suiteConfig>
Now we can do this!
Memory Link Repository
name google with new Link Google http://www.google.com
name yahoo with new Link Yahoo http://www.yahoo.com
save "google"
save "yahoo"
find all
name url
Google http://www.google.com
Yahoo http://www.yahoo.com
We can write tests with no fixture code!
But “can” is not the same as “should”!
FitNesse Pages tell us “what”
Fixtures tell us “how”
Bridging the Communication Gap
• learn how to improve communication between business people and software implementation teams
• find out how to build a shared and consistent understanding of the domain in your team
• learn how to apply agile acceptance testing to produce software genuinely fit for purpose
• discover how agile acceptance testing affects your work whether you are a programmer, business analyst or a tester
• learn how to build in quality into software projects from the start, rather than control it later
http://www.acceptancetesting.info
Upcoming events
• Games in the cloud: March 5th
• Next .NET event: March 23rd
• Web Tech Exchange: May 11-15
Where next?
• http://gojko.net
• http://www.syterra.com
• http://www.fitnesse.info