Unit Testing XQuery on MarkLogic

Preview:

DESCRIPTION

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. This slide deck is from a presentation at the MarkLogic Users Conference 2011. More info available at RockyCode.com

Citation preview

declare function testFeature() {

let $actual := feature:doFeature()

(: assert feature condition :)

};

declare function doFeature() {

() (: todo: impl :)

};

declare function doFeature() {

let $output := lotsOfLogic()

return $output

};

declare namespace its = “http://www.w3.org/2005/11/its”;

declare function buildXmlWithTranslateFlags() {

element data {

attribute its:translate {

“yes”

},

businessLogicToBuildXml();

}

};

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/*

}

};

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 :)

};

import module namespace build = “b” at “/build.xqy”;

declare function buildXml_condition1() {

(: ... :)

};

declare function buildXml_condition2() {

(: ... :)

};

(: etc. :)

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() {

(: ... :)

};

declare function bizLogic($input as element()*) {

(: ... :)

};

import module namespace logic = “logic” at “/logic.xqy”;

declare function bizLogic_insufficientInput() {

(: ... :)

};

declare function bizLogic_malformedInput() {

(: ... :)

};

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()

}

};

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”);

};

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”);

};

xdmp:get-request-field(“var”)

xdmp:redirect-response(“/page.xqy”)

xdmp:document-insert(“/trades.xml”, element beads {})

fn:collection()/dances/rain

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”)

};

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”)

};

declare function (:TEST:) isolate_noUrlNoChannels()

{

(: ... :)

};

<dependency>

<groupId>org.lds.marklogic.shared</groupId>

<artifactId>xqtest</artifactId>

<version>1.0-SNAPSHOT</version>

<type>xar</type>

</dependency>

import module namespace unit =

"http://lds.org/code/shared/xqtest/html" at

"/shared/xqtest/html.xqy";

html:test()

import module namespace unit =

"http://lds.org/code/shared/xqtest/testng" at

"/shared/xqtest/testng.xqy";

testng:test()

<channels>

<channel>

<name>Dress &amp; Grooming</name>

<path>/dress-grooming/</path>

<channels>

<!-- ... -->

<channels>

</channel>

<!-- ... -->

</channels>

...

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

...

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)

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)

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

A l l C r e a t i v e C o m m o n s 2 . 0 A t t r i b u t i o n L i c e n s e u n l e s s o t h e r w i s e n o t e d

Decoupled http://www.flickr.com/photos/daquellamanera/2213902727/ Daquella manera's photostream Water Droplet http://www.flickr.com/photos/shannonkringen/4680455907/ shannonkringen's photostream

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/photostream/ 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

Recommended