Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Testing XQuery

Unit Testing XQuery

Unit testing is a required part of a healthy software development lifecycle. Business logic in MarkLogic Xquery needs the same insurance of superb testing as any other language.

Principles: Come learn the motivation for unit testing and how test-driven development can increase your productivity writing solid Xquery code in an Agile-coding environment.

Skills: We'll code Xquery examples to learn general skills including the TDD workflow, how to isolate your code for unit testability, and how to test one thing at a time. In each case, we'll address how to apply these skills specifically to development in the MarkLogic environment.

Tools: We'll also introduce you to in-house-developed tooling for creating unit tests and running them. This tooling provides an all-Xquery method of creating test functions, annotating them as such so they're runnable in the test runner, isolating certain modules to test, and viewing clear test results.

With a few principles, skills, and tools for unit testing, you can go forward with increased confidence that the Xquery code you write on MarkLogic is more awesome than ever.

Jake Trent

April 19, 2011
Tweet

More Decks by Jake Trent

Other Decks in Technology

Transcript

  1. declare function testFeature() { let $actual := feature:doFeature() (: assert

    feature condition :) }; declare function doFeature() { () (: todo: impl :) };
  2. declare namespace its = “http://www.w3.org/2005/11/its”; declare function buildXmlWithTranslateFlags() { element

    data { attribute its:translate { “yes” }, businessLogicToBuildXml(); } };
  3. declare function buildXml() { element data { businessLogicToBuildXml(); } };

    declare namespace its = “http://www.w3.org/2005/11/its”; declare function addTranslateFlags($xml) { element {$xml/fn:name()} { attribute its:translate { “yes” }, $xml/@*, $xml/* } };
  4. import module namespace build = “b” at “/build.xqy”; declare function

    testBuildXml() { let $actual := b:buildXml() (: assert only xml is well-built :) }; import module namespace translate = “t” at “/transl8.xqy”; declare function testAddTranslateFlags() { let $actual := t:addTranslateFlags() (: assert only that translation flags added correctly :) };
  5. import module namespace build = “b” at “/build.xqy”; declare function

    buildXml_condition1() { (: ... :) }; declare function buildXml_condition2() { (: ... :) }; (: etc. :)
  6. declare function bizLogic($input as element()*) { (: ... :) };

    import module namespace logic = “logic” at “/logic.xqy”; declare function bizLogic_emptyInput() { (: ... :) }; declare function bizLogic_oneInput() { (: ... :) }; declare function bizLogic_manyInput() { (: ... :) };
  7. declare function bizLogic($input as element()*) { (: ... :) };

    import module namespace logic = “logic” at “/logic.xqy”; declare function bizLogic_insufficientInput() { (: ... :) }; declare function bizLogic_malformedInput() { (: ... :) };
  8. declare function bizLogic($input as element()*) { if (isInsufficientInput($input)) then fn:error(xs:Qname(“ASSERT”),

    “Insufficient msg”) else (: normal process... :) }; import module namespace logic = “logic” at “/logic.xqy”; declare function bizLogic_insufficientInput() { try { (: call w/ insufficient input :) } catch ($e) { if ($e/error:name eq “ASSERT”) then () else xdmp:rethrow() } };
  9. declare function businessLogic($input) { let $moreInput := /more-input[@attr eq $input]

    let $returnVal := for $item in $moreInput let $details := /detail[@id eq $item/id] return if ($details/thing eq xdmp:get-request-field(“thing-id”)) then $details else () return if (fn:exists($returnVal)) then let $audit := xdmp:document-insert(“/latest.xml”, element ok {}) return $returnVal else xdmp:redirect-response(“/empty.xqy”); };
  10. declare function businessLogic($input) { let $moreInput := /more-input[@attr eq $input]

    let $returnVal := for $item in $moreInput let $details := /detail[@id eq $item/id] return if ($details/thing eq xdmp:get-request-field(“thing-id”)) then $details else () return if (fn:exists($returnVal)) then let $audit := xdmp:document-insert(“/latest.xml”, element ok {}) return $returnVal else xdmp:redirect-response(“/empty.xqy”); };
  11. declare function feature() { let $filter := xdmp:get-request-field(“filter”) let $input

    := fn:collection()/data[@attr eq $filter] let $result := businessLogic($input) let $persist := xdmp:document-insert(“/doc.xml”, $result) return xdmp:redirect-response(“complete.xqy”) };
  12. declare function feature() { let $filter := xdmp:get-request-field(“filter”) let $input

    := fn:collection()/data[@attr eq $filter] let $result := businessLogic($input) let $persist := xdmp:document-insert(“/doc.xml”, $result) return xdmp:redirect-response(“complete.xqy”) };
  13. ... test - show only active subchannels - green test

    - show only active subchannels - red test - 1 child level all children - green test - 1 child level, 2 exist - green test - 1 child level, 2 exist - red test - 1 child level - green test - child level - red test - get closest url - green test - get closest url - red test - match level 2 - green test - match level 2 - red test - active chg - match whole tree & match lvl1 partial tree - green test - active chg - match whole tree & match lvl1 partial tree - red test - match lvl1 partial tree - red test - match whole tree - green test - match whole tree – red ...
  14. Demo'able parameters style adjustment added stylesheet for sidebar added demo

    page, adjusted reverse tree builder to handle queried docs testng runner added xqtest ver .5 - update to work with new api test - limit shallow non-hierarchical url - green test - shallow limit 1 level, 2 exist - green test - adjust test (only work with hierarchical urls) - shallow … test - shallow limit 1 level, 2 exist - red test - deep limit 1 level, 2 exist - green test - adjust test - deep limit 1 level, 2 exist - red test - limit 1 level, 2 exist - red test - level 3 active link - green test - level 3 active link - red test - level 3 list none active (and fixed level 2 test data) - green test - level 3 list none active - red cleanup - privatize fn's test - level 2 list none active - green test - level 2 list none active - red test - header only multiple level 1 channel - green test - header only multiple level 1 channel - red test - header only - green test - header only - red test - no channels data - green test - no channels data - red test - no channels - green added sidebar renderer - no channels test - red renamed build->render fn added build fn test - build max child levels of set to more - green test - no match 3 levels, 2 exist, 2 shown (fixed bug) - green test - no match 3 levels, 2 exist, 2 shown - red test - no match level 1, 2 exist - fix - green test - no match level 1, 2 exist - green test - no match levels more than exists - green test - no match level 1 - green test - no match level 1 - red cleanup long fn signatures test - show only active subchannels - green test - show only active subchannels - red test - 1 child level all children - green test - 1 child level, 2 exist - green test - 1 child level, 2 exist - red test - 1 child level - green test - child level - red test - get closest url - green test - get closest url - red test - match level 2 - green test - match level 2 - red test - active chg - match whole tree & match lvl1 partial tree - green test - active chg - match whole tree & match lvl1 partial tree - red test - match lvl1 partial tree - red test - match whole tree - green test - match whole tree - red Rename isolateChannels -> isolate Rename nav -> channel Rename nav2 -> nav Added gitignore Initial import - base test cases (no input)
  15. Demo'able parameters style adjustment added stylesheet for sidebar added demo

    page, adjusted reverse tree builder to handle queried docs testng runner added xqtest ver .5 - update to work with new api test - limit shallow non-hierarchical url - green test - shallow limit 1 level, 2 exist - green test - adjust test (only work with hierarchical urls) - shallow … test - shallow limit 1 level, 2 exist - red test - deep limit 1 level, 2 exist - green test - adjust test - deep limit 1 level, 2 exist - red test - limit 1 level, 2 exist - red test - level 3 active link - green test - level 3 active link - red test - level 3 list none active (and fixed level 2 test data) - green test - level 3 list none active - red cleanup - privatize fn's test - level 2 list none active - green test - level 2 list none active - red test - header only multiple level 1 channel - green test - header only multiple level 1 channel - red test - header only - green test - header only - red test - no channels data - green test - no channels data - red test - no channels - green added sidebar renderer - no channels test - red renamed build->render fn added build fn test - build max child levels of set to more - green test - no match 3 levels, 2 exist, 2 shown (fixed bug) - green test - no match 3 levels, 2 exist, 2 shown - red test - no match level 1, 2 exist - fix - green test - no match level 1, 2 exist - green test - no match levels more than exists - green test - no match level 1 - green test - no match level 1 - red cleanup long fn signatures test - show only active subchannels - green test - show only active subchannels - red test - 1 child level all children - green test - 1 child level, 2 exist - green test - 1 child level, 2 exist - red test - 1 child level - green test - child level - red test - get closest url - green test - get closest url - red test - match level 2 - green test - match level 2 - red test - active chg - match whole tree & match lvl1 partial tree - green test - active chg - match whole tree & match lvl1 partial tree - red test - match lvl1 partial tree - red test - match whole tree - green test - match whole tree - red Rename isolateChannels -> isolate Rename nav -> channel Rename nav2 -> nav Added gitignore Initial import - base test cases (no input)
  16. Green Apple (modified) http://www.flickr.com/photos/_fxr/2335186114/ _FXR's photostream Salt Lake Temple http://www.flickr.com/photos/midiman/2503776540/

    midiman's photostream Belay http://www.flickr.com/photos/picsbycam/5173647461/ Cameron Cassan's photostream Thinker http://www.flickr.com/photos/garysoup/2705102139/ Gary Soup's photostream Multipurpose Tool http://www.flickr.com/photos/paalb/11772559/ Pål Berge's photostream Clean Up http://www.flickr.com/photos/emilyrides/5188289325/lightbox/ emilydickinsonridesabmx's photostream Cliff http://www.flickr.com/photos/elsie/144702426/ Elsie esq.'s photostream Paper Pile http://www.flickr.com/photos/loty/326761635/ lotyloty's photostream Candles http://www.flickr.com/photos/picsbycam/4023646774/in/photostream/ Cameron Cassan's photostream Elephant http://www.flickr.com/photos/greenboots76/2924276160/ Henry Brett's photostream Assembly Line http://www.flickr.com/photos/jurvetson/5201796697/ jurvetson's photostream Chihuahua http://www.flickr.com/photos/62337512@N00/3727104807/ apdk's photostream Angry Dog http://www.flickr.com/photos/javiercito/2083111412/lightbox/ Javiercit0's photostream Clean up Pet http://www.flickr.com/photos/pointshoot/1144799868/ Eddie~S' photostream Hugging Fingers http://www.flickr.com/photos/ganesha_isis/4439563089/ ganesha.isis' photostream Fail Whale http://www.flickr.com/photos/coletivomambembe/3882172324/ Coletivo Mambembe's photostream Lego Death Star http://www.flickr.com/photos/dudeoflego/5104751355/ Dude of Lego's photostream Road Runner http://www.flickr.com/photos/snowpeak/4815685925/ snowpeak's photostream Keyboard Sleep http://www.flickr.com/photos/ytruly/1718468702/ YTruly's photostream Lotus http://www.flickr.com/photos/thecarspy/2571799871/in/photostream/ The Car Spy's photostream Neon Pipes http://www.flickr.com/photos/krossbow/3619931451/ krossbow's photostream - CC Attribution license Calculator http://www.flickr.com/photos/scoobay/2463236523/ Scoobay's photostream Dragon Boat http://www.flickr.com/photos/wiifm69/3410782558/ wiifm's photostream Ping Pong http://www.flickr.com/photos/ncc_badiey/4932760753/ Nima Badiey's photostream Solitary Confinement http://www.flickr.com/photos/59195512@N00/143521274/ dospaz's photostream Flags http://www.flickr.com/photos/markchapmanphoto/5138832677/ ::: Radar Communication :::'s photostream Pointing Caterpillar http://www.flickr.com/photos/pinkstockphotos/5266977224/ PinkStock Photos!'s photostream Multiplication http://www.flickr.com/photos/somegeekintn/4048155967/ somegeekintn's photostream All Creative Co mmons 2.0 At tribution License unless otherwise noted Decoupled http://www.flickr.com/photos/daquellamanera/2213902727/ Daquella manera's photostream Water Droplet http://www.flickr.com/photos/shannonkringen/4680455907/ shannonkringen's photostream
  17. Pig Egg http://www.flickr.com/photos/katerha/5423107783/ katerha's photostream Spaghetti Noodle http://www.flickr.com/photos/pinksherbet/2201247567/ Pink Sherbet

    Photography's photostream Girl Eating Spaghetti http://www.flickr.com/photos/pinksherbet/5008273559/ Pink Sherbet Photography's photostream Salute Flag http://www.flickr.com/photos/soldiersmediacenter/3920702814/ The U.S. Army's photostream Camoflauge Lizard http://www.flickr.com/photos/lofink/4453281926/ dlofink's photostream Call on Beach http://www.flickr.com/photos/zitona/2268296925/ » Zitona «'s photostream Indian Chief http://www.flickr.com/photos/boston_public_library/4100786887/in/photo stream/ Boston Public Library's photostream Ninja Turtle http://www.flickr.com/photos/86805724@N00/1581833575/ ianmalcm's photostream Phone Booth http://www.flickr.com/photos/bexwalton/4204409348/ Bex.Walton's photostream Suit http://www.flickr.com/photos/pss/4830803189/ Paul Stevenson's photostream Underwater http://www.flickr.com/photos/andreweick/4000567498/in/photostream/ AndrewEick's photostream Picasso http://www.flickr.com/photos/oddsock/101164507/ oddsock's photostream Spider Tunnel http://www.flickr.com/photos/b1gw1ght/900924265/ b1gw1ght's photostream Safety Net http://www.flickr.com/photos/iamchadhearmesnore/3629410556/ iamchad's photostream Black Box http://www.flickr.com/photos/amagill/34762677/ AMagill's photostream Tool Belt http://www.flickr.com/photos/blue_diamond/3995257652/ Blue Diamond Photography's photostream The Swede By David Quinn, used with permission Garden Gnome http://www.flickr.com/photos/mukluk/196177233/ Dano's photostream Blueprint http://www.flickr.com/photos/wscullin/3770016707/ Will Scullin's photostream Flux Capacitor http://www.flickr.com/photos/popculturegeek/4533455371/ popculturegeek.com's photostream Power Plug http://www.flickr.com/photos/randomurl/438112948/ Zevotron's photostream Runner http://www.flickr.com/photos/lululemonathletica/5197327623/lightbox/ lululemon athletica's photostream Yoga Man http://www.flickr.com/photos/lululemonathletica/4774517755/ lululemon athletica's photostream Lego City Men http://www.flickr.com/photos/mac_filko/5491561002/ mac_filko's photostream Port Said http://www.flickr.com/photos/48722974@N07/5036484008/ eutrophication&hypoxia's photostream Vote for Pedro http://www.flickr.com/photos/emdot/79863648/ emdot's photostream Dusty Road http://www.flickr.com/photos/generated/5554654197/ jared's photostream Mexican Hat Rock Formation http://www.flickr.com/photos/wolfgangstaudt/4879456199/in/set- 72157624891093384 Wolfgang Staudt's photostream Red Apple (modified) http://www.flickr.com/photos/emzee/273289101/ *Micky's photostream Kodak Roll http://www.flickr.com/photos/picsbycam/4550970565/in/photostream/ Cameron Cassan's photostream Gnuolane Free font http://typodermicfonts.com Free for personal and commercial use