"Unit tests have been compared with shining a flashlight into a dark room in search of a monster. Shine the light into the room and then into all the scary corners. It doesn't mean the room is monster free - just that the monster isn't standing where you've shined your flashlight."
[<Fact>]
let``customer is important if she has X subscriptions``() =// Arrange phaseletinputXml="""<customer> <firstName>John</firstName> <lastName>Doe</lastName> <email>john.doe@example.com</com> <subscriptions> <subscription> <type>... ... </customer> """// Act phaseletresult=classifyCustomerinputXml// Assert phaseAssert.True(result.IsImportantCustomer)
[<Theory>]
[<InlineData(5, 3, 8)>]
[<InlineData(2, 2, 4)>]
[<InlineData(-4, 9, 5)>]
let``add gives sum of two components``(x, y, expected) =letactual=addxyAssert.Equal(expected, actual)
Add - using AutoFixture library
1: 2: 3: 4: 5: 6:
[<Theory>]
[<AutoData>]
let``add gives sum of two components``(x, y) =letexpected=x+yletactual=addxyAssert.Equal(expected, actual)
run only once?
what about using the "+" operator?
Add - using Property Based Approach
Demo
How to come up with a good test
applicable to a more complex problem
Scott Wlaschin's list
"Different paths, same destination"
"There and back again"
"Some things never change"
"The more things change, the more they stay the same"
[<Property>]
let``parsing a stringified JSON gives original result`` (original:JSON) =letstringified=stringifyoriginalletparsed=parsestringifiedparsed=original
"The more things change, the more they stay the same"
1: 2: 3: 4: 5:
[<Property>]
let``distinct is idemptotent`` (input:list<'a>) =letfirstTurn=distinctinputletsecondTurn=distinctfirstTurnfirstTurn=secondTurn
"The test oracle"
1: 2: 3: 4: 5:
[<Property>]
let``optimised version really works`` (input) =letoptimisedResult=hiperFastConcurrentAlgorithminputletplainResult=simpleButSlowerAlgorithminputplainResult=optimisedResult
How we use it in Phoenix
Desktop publishing
Quark XPress
Adobe InDesign
Quark Stack
Quark Publishing Platform
Quark XML Author
Quark XPress + Quark XPress Server
Quark XPress Server
Quark XPress template + Modifier XML = PDF
Desktop publishing
Desktop publishing automation
Modifier XML
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
<LAYOUT><PAGESEQUENCEMASTERREFERENCE="Main"><STORY><PARAGRAPHPARASTYLE="m_header_1"><RICHTEXT>My first publication</RICHTEXT></PARAGRAPH><PARAGRAPHPARASTYLE="m_body"><RICHTEXT>Hello </RICHTEXT><RICHTEXTBOLD="TRUE">world!</RICHTEXT></PARAGRAPH></STORY></PAGESEQUENCE></LAYOUT>
Dita XML
(or rather Phoenix-Dita XML)
1: 2: 3: 4: 5: 6:
<topic><title>My first publication</title><body><p>Hello <b>world!</b></p></body></topic>
letschema=XmlSchema.Parse"Modifier.xsd"
[<Property>]
let``modifier XML conforms to schema`` (topic:XDocument) =letoutput=xsltTransform"topic.xslt"topicdoesNotThrow (fun () ->schema.Validateoutput)
alternative -> schema-aware XSLT processor
Moar tests
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
[<Property>]
let``if text node under "b" element then richtext has bold`` (topic) =letoutput=xsltTransform"topic.xslt"topiclettextNodes=topic|>xpath"//text()"letrichtexts=output|>xpath"//RICHTEXT"
(textNodes, richtexts)
||>Seq.zip|>Seq.filter (fst>>xpath"ancestor::b")
|>Seq.forAll (snd>>xpath"@BOLD = 'TRUE'")
<topic><title>My first publication</title><body><imagehref="unicorn.pdf"><p>Hello <b>world!</b></p><table><title>table</title><tbody><row><entry>aaa</entry></row></tbody></table></body></topic>