<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>AgileIQ Blog</title><link>http://www.solutionsiq.com/resources/agileiq-blog/</link><description>RSS feeds for the Agile IQ Blog</description><ttl>60</ttl><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AgileIQBlog" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="agileiqblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/78857/Agile-Open-Northwest-2012-Was-a-Fantastic-Conference#Comments</comments><slash:comments>0</slash:comments><title>Agile Open Northwest 2012 Was a Fantastic Conference</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/78857/Agile-Open-Northwest-2012-Was-a-Fantastic-Conference</link><description>&lt;p&gt;by Emily VanDeWalker&lt;/p&gt;
&lt;p&gt;Agile Open Northwest 2012 was my first Open Space conference, and it was just that &amp;ndash; open.&lt;img src="http://www.solutionsiq.com/Portals/93486/images/solutionsiq-agile-open-northwest.jpg" border="0" alt="Agile Open Northwest 2012" class="alignRight" style="float: right;" /&gt; Walking through the front doors, people were scattered around the main gathering room and in the breakfast room mingling over fruit and pastries, talking about what they wanted to get out of the conference. As the conference introduction started, the group sat in a circle of chairs, leaving the center open for the speaker. The conference outline was explained: if you want to host a session, write the title on a sheet of paper, pick the time and location based on what is listed in the &amp;ldquo;Marketplace&amp;rdquo; on the wall, and give a 15-30 second description to the group. As the sessions were announced, I was pleasantly surprised that a wide range of topics were proposed. I was expecting a plethora of technical sessions that I wouldn&amp;rsquo;t be able to relate to in my operations position. Instead, I found that I wanted to attend more sessions than I had time for. The speaker anticipated this, however, and let the attendees know that we were welcome to jump from session to session and were not required to sit through a session from start to finish. I didn&amp;rsquo;t jump from session to session, though. I found that I was far too interested in the current session and didn&amp;rsquo;t want to leave!&lt;/p&gt;
&lt;p&gt;The most interesting thing about the conference is something that I realized on the afternoon of the second day: many of the sessions that I attended were related to human behavior within Scrum and Agile teams, and everyone actively participated. These sessions included discussions about what makes greatness, resolving conflict to remove impediments, coaching &amp;ldquo;smells&amp;rdquo;, and self-organizing teams. During one particular session on the first day, someone mentioned that it would be nice for someone to host a session on a topic that was brought up; by the morning of the second day, someone took the initiative to host that session and post it on the wall. I later learned that the host was a first-time attendee to Open Space conferences. I think it speaks volumes that even as a first-timer, she was comfortable enough with the group that she would step up in that capacity.&lt;/p&gt;
&lt;p&gt;At the end of day one, the group gathered back in the main room to share what they had learned. At closing, I heard someone say, &amp;ldquo;Does anyone that I &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; know want to go out for dinner?&amp;rdquo; I have to admit that is something that I didn&amp;rsquo;t think I would hear. I figured everyone would form their groups and stick with them. I&amp;rsquo;m glad I was wrong.&lt;/p&gt;
&lt;p&gt;As the conference came to a close on the second day, the microphone was passed around so we could all express appreciation to whoever stood out in our experiences throughout the conference. This was followed by a friendly retrospective, where the organizers happily accepted all feedback for future conference planning.&lt;/p&gt;
&lt;p&gt;During the introduction on the first day, I was expecting maybe 20-30 sessions to be proposed. Much to my surprise, there were 77 sessions over the span of just two days! I took away a lot of valuable information, and I am already looking forward to next year&amp;rsquo;s Agile Open Northwest.&lt;/p&gt;
&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/78857/Agile-Open-Northwest-2012-Was-a-Fantastic-Conference&lt;/span&gt;</description><pubDate>Thu, 16 Feb 2012 19:04:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:78857</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/78219/Agile-Software-Development-BDD-With-Spock-and-Selenium#Comments</comments><slash:comments>0</slash:comments><title>Agile Software Development: BDD With Spock and Selenium</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/78219/Agile-Software-Development-BDD-With-Spock-and-Selenium</link><description>&lt;p&gt;by Tim Myer&lt;/p&gt;
&lt;h2&gt;Goal&lt;/h2&gt;
&lt;p&gt;To develop a web site specification-first using Spock and Selenium WebDriver.&lt;/p&gt;
&lt;h4&gt;tl;dr&lt;/h4&gt;
&lt;p&gt;The sample code for this project is &lt;a href="https://github.com/timezra/course_registry" rel="nofollow" title="available on github" target="_blank"&gt;available on github&lt;/a&gt; and will be a helpful resource for following this article. The interesting technologies showcased include &lt;a href="http://code.google.com/p/spock/" rel="nofollow" title="Spock" target="_blank"&gt;Spock&lt;/a&gt;, &lt;a href="http://seleniumhq.org/projects/webdriver/"&gt;Selenium WebDriver&lt;/a&gt;, &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects" rel="nofollow" title="Selenium PageObjects" target="_blank"&gt;Selenium PageObjects&lt;/a&gt;, &lt;a href="http://saucelabs.com/ondemand" rel="nofollow" title="Sauce OnDemand" target="_blank"&gt;Sauce OnDemand&lt;/a&gt;, &lt;a href="http://gradle.org/" rel="nofollow" title="Gradle" target="_blank"&gt;Gradle&lt;/a&gt; and &lt;a href="http://grails.org/" rel="nofollow" title="Grails 2.0" target="_blank"&gt;Grails 2.0&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Project&lt;/h2&gt;
&lt;p&gt;Suppose our product owner would like to publish a website for teachers to schedule their classes and for students to register for those courses. At the first backlog grooming, the product owner has prioritized the stories that would constitute a &lt;a href="http://en.wikipedia.org/wiki/Minimum_viable_product" rel="nofollow" title="minimum viable product" target="_blank"&gt;minimum viable product&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;User Stories&lt;/h2&gt;
&lt;p&gt;During the team's first sprint planning meeting, we sized the stories, accepted four into the sprint, and have added tasks for each. Our story board for the first sprint contains &lt;a href="http://net.tutsplus.com/articles/news/create-a-sticky-note-effect-in-5-easy-steps-with-css3-and-html5/" rel="nofollow" title="sticky notes" target="_blank"&gt;sticky notes&lt;/a&gt; for our user stories, the acceptance criteria and the individual tasks for each story.&lt;/p&gt;
&lt;br /&gt;
&lt;div style="overflow-x: auto; overflow-y: hidden; padding: 1em; background-color: white; border-style: groove; border-width: medium;"&gt;
&lt;div style="float: left; text-decoration: none; color: #000; font-family: 'Indie Flower', cursive; width: 96em;"&gt;&lt;!-- User Story 1 --&gt;&lt;br /&gt;
&lt;div style="float: left; padding: 1em;"&gt;
&lt;div onmouseout="
      this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
      this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
      this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
      this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
      this.style.OTransform='rotate(-3deg)';
      this.style.MsTransform='rotate(-3deg)';
      this.style.WebkitTransform='rotate(-3deg)';
      this.style.MozTransform='rotate(-3deg)';  
      this.style.zIndex='0';" onmouseover="
      this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
      this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
      this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
      this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)';
      this.style.OTransform='scale(1.25)';  
      this.style.MsTransform='scale(1.25)';  
      this.style.WebkitTransform='scale(1.25)';  
      this.style.MozTransform='scale(1.25)';  
      this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(-3deg); -ms-transform: rotate(-3deg); -webkit-transform: rotate(-3deg); -moz-transform: rotate(-3deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ffc; height: 10em; width: 10em; padding: 1em;"&gt;
&lt;p&gt;As a teacher &lt;br /&gt; I want to sign up &lt;br /&gt; So I can add courses&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(1deg)';
                  this.style.MsTransform='rotate(1deg)';
                  this.style.WebkitTransform='rotate(1deg)';
                  this.style.MozTransform='rotate(1deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(1deg); -ms-transform: rotate(1deg); -webkit-transform: rotate(1deg); -moz-transform: rotate(1deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ccf; height: 10em; width: 20em; padding: 1em;"&gt;Acceptance Criteria:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;User is greeted with intro screen&lt;/li&gt;
&lt;li&gt;User is able to register as a teacher or to login&lt;/li&gt;
&lt;li&gt;After registration or login, a teacher sees account info&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- User Story 2 --&gt;
&lt;div style="float: left; padding: 1em;"&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(4deg)';
                  this.style.MsTransform='rotate(4deg)';
                  this.style.WebkitTransform='rotate(4deg)';
                  this.style.MozTransform='rotate(4deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)';
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(4deg); -ms-transform: rotate(4deg); -webkit-transform: rotate(4deg); -moz-transform: rotate(4deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ffc; height: 10em; width: 10em; padding: 1em;"&gt;
&lt;p&gt;As a student &lt;br /&gt; I want to sign up &lt;br /&gt; So I can take courses&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(-2deg)';
                  this.style.MsTransform='rotate(-2deg)';
                  this.style.WebkitTransform='rotate(-2deg)';
                  this.style.MozTransform='rotate(-2deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)';
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(-2deg); -ms-transform: rotate(-2deg); -webkit-transform: rotate(-2deg); -moz-transform: rotate(-2deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ccf; height: 10em; width: 20em; padding: 1em;"&gt;Acceptance Criteria:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;User is able to register or to login as a student&lt;/li&gt;
&lt;li&gt;After registration or login, a student sees account info&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- User Story 3 --&gt;
&lt;div style="float: left; padding: 1em;"&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(-2deg)';
                  this.style.MsTransform='rotate(-2deg)';
                  this.style.WebkitTransform='rotate(-2deg)';
                  this.style.MozTransform='rotate(-2deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)'; 
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(-2deg); -ms-transform: rotate(-2deg); -webkit-transform: rotate(-2deg); -moz-transform: rotate(-2deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ffc; height: 10em; width: 10em; padding: 1em;"&gt;
&lt;p&gt;As a teacher &lt;br /&gt; I want to add courses &lt;br /&gt; So students can register for them&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(3deg)';
                  this.style.MsTransform='rotate(3deg)';
                  this.style.WebkitTransform='rotate(3deg)';
                  this.style.MozTransform='rotate(3deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)'; 
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(3deg); -ms-transform: rotate(3deg); -webkit-transform: rotate(3deg); -moz-transform: rotate(3deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ccf; height: 10em; width: 20em; padding: 1em;"&gt;Acceptance Criteria:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;A teacher can add a course&lt;/li&gt;
&lt;li&gt;Courses occur in a semester&lt;/li&gt;
&lt;li&gt;Courses occur in timeslots&lt;/li&gt;
&lt;li&gt;Courses can have prerequisites&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- User Story 4 --&gt;
&lt;div style="float: left; padding: 1em;"&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(4deg)';
                  this.style.MsTransform='rotate(4deg)';
                  this.style.WebkitTransform='rotate(4deg)';
                  this.style.MozTransform='rotate(4deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)'; 
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(4deg); -ms-transform: rotate(4deg); -webkit-transform: rotate(4deg); -moz-transform: rotate(4deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ffc; height: 10em; width: 10em; padding: 1em;"&gt;
&lt;p&gt;As a student &lt;br /&gt; I want to register for courses &lt;br /&gt; So I can get credits toward my degree&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div onmouseout="
                  this.style.boxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.msBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.WebkitBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.MozBoxShadow='5px 5px 7px rgba(33,33,33,.7)';
                  this.style.OTransform='rotate(-1deg)';
                  this.style.MsTransform='rotate(-1deg)';
                  this.style.WebkitTransform='rotate(-1deg)';
                  this.style.MozTransform='rotate(-1deg)';  
                  this.style.zIndex='0';" onmouseover="
                  this.style.boxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.msBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.WebkitBoxShadow='10px 10px 7px rgba(0,0,0,.7)';  
                  this.style.MozBoxShadow='10px 10px 7px rgba(0,0,0,.7)'; 
                  this.style.OTransform='scale(1.25)';  
                  this.style.MsTransform='scale(1.25)';  
                  this.style.WebkitTransform='scale(1.25)';  
                  this.style.MozTransform='scale(1.25)';  
                  this.style.zIndex='1';" style="-webkit-backface-visibility: hidden; box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -ms-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -webkit-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -moz-box-shadow: 5px 5px 7px rgba(33, 33, 33, .7); -o-transform: rotate(-1deg); -ms-transform: rotate(-1deg); -webkit-transform: rotate(-1deg); -moz-transform: rotate(-1deg); -o-transition: -o-transform .15s linear; -ms-transition: -ms-transform .15s linear; -webkit-transition: -webkit-transform .15s linear; -moz-transition: -moz-transform .15s linear; position: relative; z-index: 0; background: #ccf; height: 10em; width: 20em; padding: 1em;"&gt;Acceptance Criteria:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;A student can register for a course&lt;/li&gt;
&lt;li&gt;A student must take any pre-reqs before registering for a course&lt;/li&gt;
&lt;li&gt;A student cannot take 2 courses that occur in the same timeslot&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;div style="clear: both;"&gt;&lt;/div&gt;
&lt;h2&gt;Project Structure&lt;/h2&gt;
&lt;p&gt;We will create a top-level project &lt;em&gt;course_registry&lt;/em&gt; and the two sub-projects &lt;em&gt;web&lt;/em&gt; and &lt;em&gt;specifications&lt;/em&gt;. We will also create a &lt;em&gt;build.gradle&lt;/em&gt; file in the root along with &lt;em&gt;settings.gradle&lt;/em&gt; and a &lt;em&gt;build.gradle&lt;/em&gt; file in the &lt;em&gt;specifications&lt;/em&gt; subproject for running automated acceptance tests (While &lt;a href="http://www.gradle.org/userguide/0.5.2/userguidech17.html#x48-13000017.2.1" rel="nofollow" title="this is not strictly necessary" target="_blank"&gt;this is not strictly necessary&lt;/a&gt;, it will help to keep our project boundaries clear).&lt;/p&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;course_registry&lt;br /&gt; &amp;nbsp;&amp;nbsp; .&lt;br /&gt; &amp;nbsp;&amp;nbsp;|____build.gradle&lt;br /&gt; &amp;nbsp;&amp;nbsp;|____settings.gradle&lt;br /&gt; &amp;nbsp;&amp;nbsp;| specifications&lt;br /&gt; &amp;nbsp;&amp;nbsp;| |____build.gradle&lt;br /&gt; &amp;nbsp;&amp;nbsp;| web&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;course_registry/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;allprojects&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;apply&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;plugin:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'eclipse'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;version&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'1.0.0-SNAPSHOT'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;group&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'timezra.course_registry'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;subprojects&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;sourceCompatibility&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;6&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;course_registry/settings.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;include&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'web'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'specifications'&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;course_registry/specifications/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;apply&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;plugin:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'groovy'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;repositories&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenCentral()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://m2repo.spockframework.org/snapshots"&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;dependencies&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;groovy&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.codehaus.groovy'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'groovy'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'1.8.5'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;testCompile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.spockframework'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'spock-core'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'0.6-groovy-1.8-SNAPSHOT'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;testCompile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.seleniumhq.selenium'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'selenium-java'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'2.16.1'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;testCompile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'junit'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'junit'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'4.10'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;We will create a &lt;em&gt;src/test/groovy&lt;/em&gt; folder in the &lt;em&gt;specifications&lt;/em&gt; project. At this point we can generate Eclipse .project and .classpath files for all the projects from the project root in order to work within an IDE.&lt;/p&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;br /&gt; &lt;span style="color: green;"&gt;course_registry $&amp;gt;&lt;/span&gt;&amp;nbsp;gradle eclipseProject&lt;br /&gt; &lt;span style="color: green;"&gt;course_registry $&amp;gt;&lt;/span&gt;&amp;nbsp;gradle eclipseClasspath&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;The Teacher Registration Spec&lt;/h2&gt;
&lt;p&gt;We are now able to write the first specification for our acceptance criteria.&lt;/p&gt;
&lt;br /&gt; &lt;em&gt;timezra/course_registry/TeacherRegistrationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.course_registry&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;java.util.concurrent.TimeUnit.SECONDS&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.firefox.FirefoxDriver&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TeacherRegistrationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;setup()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;FirefoxDriver()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.manage().timeouts().implicitlyWait&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SECONDS&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;cleanup()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.quit()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;is&amp;nbsp;greeted&amp;nbsp;with&amp;nbsp;an&amp;nbsp;intro&amp;nbsp;screen"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.get&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://localhost:8080/course_registry"&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.title&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"Course&amp;nbsp;Registry&amp;nbsp;Home"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;We can run this spec and watch it fail.&lt;/p&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: green;"&gt;course_registry $&amp;gt;&lt;/span&gt;&amp;nbsp;gradle test --info&lt;br /&gt; ....&lt;br /&gt; Test a user is greeted with an intro screen(timezra.course_registry.TeacherRegistrationSpec) FAILED: org.gradle.messaging.remote.internal.PlaceholderException: org.spockframework.runtime.SpockComparisonFailure: Condition not satisfied:&lt;br /&gt; &lt;br /&gt; driver.title == "Course Registry Home"&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;false&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;17 differences (15% similarity)&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Pr)o(bl-)e(m) (load)i(ng--) (pag)e&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(C-)o(urs)e(-) (Reg-)i(stry) (Hom)e&lt;br /&gt; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Problem loading page&lt;br /&gt; org.openqa.selenium.firefox.FirefoxDriver@4532be10&lt;br /&gt; &lt;br /&gt; Test timezra.course_registry.TeacherRegistrationSpec FAILED&lt;br /&gt; Gradle Worker 1 finished executing tests.&lt;br /&gt; 1 test completed, 1 failure&lt;br /&gt; &lt;br /&gt; &lt;span style="color: red;"&gt;FAILURE: Build failed with an exception.&lt;/span&gt;&lt;br /&gt; ....&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;Satisfying the Spec&lt;/h2&gt;
&lt;p&gt;Suppose the team decides to use Grails 2.0 to implement the specification. This is not a restriction based on our other technology choices, since gradle is &lt;a href="http://www.gradle.org/userguide/0.5.2/userguidech17.html#x48-12700017.1"&gt;a general purpose build tool&lt;/a&gt; and since our specification defines how a user will interact with our web project entirely through a browser. The decision is based on the convenience of the framework, community support, the plug-in ecosystem and the skills of the developers.&lt;/p&gt;
&lt;p&gt;First, we need to create an empty &lt;em&gt;web/grails-app&lt;/em&gt; directory to indicate to the grails bootstrap that the project will be a grails application.&lt;br /&gt; Then, we will configure our web build for Grails 2.0 in a new &lt;em&gt;web/build.gradle&lt;/em&gt; file.&lt;/p&gt;
&lt;em&gt;web/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;buildscript&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;repositories&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenCentral()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'https://repository.jboss.org/nexus/content/groups/public/'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'http://repo.grails.org/grails/repo'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;dependencies&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;classpath&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-gradle-plugin'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'1.1.0'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'2.0.0'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;apply&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;plugin:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;dependencies&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;compile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-resources'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;compile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-crud'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;compile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-hibernate'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;compile&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-datasource'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-log4j'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-url-mappings'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-gsp'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-filters'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-scaffolding'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-services'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'org.grails'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-plugin-servlets'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;grailsVersion&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'com.h2database'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'h2'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'1.3.163'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'net.sf.ehcache'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'ehcache-core'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'2.4.6'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;repositories&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenCentral()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'https://repository.jboss.org/nexus/content/groups/public/'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'http://repo.grails.org/grails/repo'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;From the project root we will initialize the grails project.&lt;/p&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: green;"&gt;course_registry $&amp;gt;&lt;/span&gt;&amp;nbsp;gradle grails-init&lt;br /&gt; :web:grails-init&lt;br /&gt; The ResolvedArtifact.getResolvedDependency() method is deprecated and will be removed in the next version of Gradle.&lt;br /&gt; &lt;span style="color: olive;"&gt;|&lt;/span&gt; Configuring classpath&lt;br /&gt; &lt;span style="color: red;"&gt;| Error&lt;/span&gt; log4j:WARN No appenders could be found for logger (org.springframework.core.io.support.PathMatchingResourcePatternResolver).&lt;br /&gt; &lt;span style="color: red;"&gt;| Error&lt;/span&gt; log4j:WARN Please initialize the log4j system properly.&lt;br /&gt; &lt;span style="color: red;"&gt;| Error&lt;/span&gt; log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.&lt;br /&gt; &lt;span style="color: olive;"&gt;|&lt;/span&gt; Environment set to development.....&lt;br /&gt; &lt;br /&gt; BUILD SUCCESSFUL&lt;br /&gt; &lt;br /&gt; Total time: 1 mins 36.328 secs&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;We can satisfy the spec simply by modifying &lt;em&gt;application.properties&lt;/em&gt; with the expected web application deployment path and project version, the homepage to include the expected title, and &lt;em&gt;messages.properties&lt;/em&gt; to contain the expected messages.&lt;/p&gt;
&lt;em&gt;web/application.properties&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;app.grails.version&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2.0.0&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;app.name&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;course_registry&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;app.servlet.version&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;2.5&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;app.version&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;1.0.0-SNAPSHOT&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;web/grails-app/views/index.gsp&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;html&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;head&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;title&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;g:message&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;code&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"home.title"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;title&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;meta&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;name&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"layout"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;content&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"main"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;style&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;type&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"text/css"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;media&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"screen"&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-style: italic; color: #3f7f7f;"&gt;#pageBody&lt;/span&gt;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;margin-left&lt;/span&gt;:&amp;nbsp;&lt;span style="font-style: italic; color: #2a00e1;"&gt;280px&lt;/span&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;margin-right&lt;/span&gt;:&amp;nbsp;&lt;span style="font-style: italic; color: #2a00e1;"&gt;20px&lt;/span&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;style&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;head&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;body&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;div&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;id&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"pageBody"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;class&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"dialog"&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;p&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;g:message&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;code&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"home.welcome.message"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #008080;"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;p&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;div&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;body&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;html&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;web/grails-app/i18n/messages.properties&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;....&lt;br /&gt; &lt;span style="color: #000000;"&gt;home.title&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;Course&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;Registry&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;Home&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;home.welcome.message&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;Welcome&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;to&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;the&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;course&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;registry.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;We can now add hooks to the specifications project to stop and start the web application before and after running the specifications, respectively.&lt;/p&gt;
&lt;em&gt;specifications/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;test.dependsOn&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;':web:webStart'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;gradle.taskGraph.afterTask&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Task&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;task,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TaskState&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;state&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;':specifications:test'&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;task.path)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;':web'&lt;/span&gt;&lt;span style="color: #000000;"&gt;).tasks.getByPath(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'webStop'&lt;/span&gt;&lt;span style="color: #000000;"&gt;).execute()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;These hooks depend on a specific interface in the &lt;em&gt;web&lt;/em&gt; project, i.e., the existence of the tasks &lt;em&gt;webStart&lt;/em&gt; and &lt;em&gt;webStop&lt;/em&gt;. We can deploy the Grails 2.0 artifact to an &lt;a href="http://gradle.org/docs/current/userguide/jetty_plugin.html"&gt;embedded Jetty server&lt;/a&gt; through gradle to satisfy this interface.&lt;/p&gt;
&lt;em&gt;web/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;apply&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;plugin:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'jetty'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;stopPort&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;8001&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;safeWord&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'banana'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;task&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;webStart(dependsOn:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'grails-war'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;tasks.getByPath(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'jettyRunWar'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.webApp&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;File(projectDir,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"target/course_registry-${version}.war"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.contextPath&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'course_registry'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.daemon&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;true&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.stopPort&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;stopPort&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.stopKey&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;safeWord&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyRunWar.execute()&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;task&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;webStop&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyStop&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;tasks.getByPath(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'jettyStop'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyStop.stopPort&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;stopPort&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyStop.stopKey&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;safeWord&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;jettyStop.execute()&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;The first specification should now be satisfied.&lt;/p&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;br /&gt; &lt;span style="color: green;"&gt;course_registry $&amp;gt;&lt;/span&gt;&amp;nbsp;gradle test --info&lt;br /&gt; ....&lt;br /&gt; Started Jetty Server&lt;br /&gt; Gradle Worker 1 executing tests.&lt;br /&gt; Test a user is greeted with an intro screen(timezra.course_registry.TeacherRegistrationSpec) PASSED&lt;br /&gt; Gradle Worker 1 finished executing tests.&lt;br /&gt; ....&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; &lt;strong&gt;NB:&lt;/strong&gt; The Jetty plugin must be applied before the grails plugin, or else you will see an error similar to the following:&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: black; color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="color: red;"&gt;FAILURE: Build failed with an exception.&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; * Where:&lt;br /&gt; Build file '/path/to/course_registry/web/build.gradle' line: 38&lt;br /&gt; &lt;br /&gt; * What went wrong:&lt;br /&gt; A problem occurred evaluating project ':web'.&lt;br /&gt; Cause: Cannot add task ':web:clean' as a task with that name already exists.&lt;br /&gt; &lt;br /&gt; * Try:&lt;br /&gt; Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.&lt;br /&gt; &lt;br /&gt; &lt;span style="color: red;"&gt;BUILD FAILED&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; Total time: 7.624 secs&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;Adding another test for our second acceptance criterion should be straightforward now that our infrastructure is in place.&lt;/p&gt;
&lt;em&gt;timezra/course_registry/TeacherRegistrationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;can&amp;nbsp;register&amp;nbsp;as&amp;nbsp;a&amp;nbsp;teacher"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.get&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://localhost:8080/course_registry"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;teacherLink&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.id(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'teacher_link'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;teacherLink.click()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.id(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'name'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'John&amp;nbsp;Doe'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;email&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.id(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'email'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;email,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"${UUID.&lt;/span&gt;&lt;span style="color: #000000; font-style: italic;"&gt;randomUUID&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;()}@rutgers.edu"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;password&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.id(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'password'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;password,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'1234567'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;create&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.id(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'create'&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;create.click()&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.title&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'Show&amp;nbsp;Teacher'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.findElement(By.className(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'message'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)).text&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/Teacher&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;\d+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;created/&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;type(field,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;text)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;field.clear()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;field.sendKeys&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;text&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;We can satisfy this specification by generating a Grails &lt;em&gt;Teacher&lt;/em&gt; domain object with fields for the name, email and password, along with a Grails controller that uses dynamic scaffolding to generate the view and actions available, and by adding a link to the scaffolded &lt;em&gt;Create Teacher&lt;/em&gt; page on our &lt;em&gt;web/grails-app/views/index.gsp&lt;/em&gt;. Since the point of this tutorial is not to cover basic Grails development, we do not need to go into those specifics here, but sample code can be found on the &lt;a href="https://github.com/timezra/course_registry"&gt;project site&lt;/a&gt; or in any &lt;a href="http://grails.org/Tutorials" rel="nofollow" title="Grails tutorial" target="_blank"&gt;Grails tutorial&lt;/a&gt; for further reference.&lt;/p&gt;
&lt;h2&gt;Page Objects&lt;/h2&gt;
&lt;p&gt;Before we get too far with automating our acceptance criteria, we should begin to look towards a more abstract representation of the testable components of our application. From the second acceptance test above, we can already see patterns emerging. For example, when we navigate to a particular page, it would be convenient to identify that we are on the correct page, perhaps by its title. It would also be convenient to represent each view in the application as its own object, and each view could encapsulate its specific &lt;em&gt;WebElement&lt;/em&gt;s. Finally, there is a small set of actions available for any &lt;em&gt;WebElement&lt;/em&gt; on a page, and it would be helpful to build these actions into a testing DSL. Fortunately, by combining the &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects"&gt;Page Object&lt;/a&gt; pattern and Groovy's dynamic language features, we can achieve all these goals with a minimal amount of code.&lt;/p&gt;
&lt;p&gt;As we are satisfying the specifications for all the &lt;a href="#user_stories"&gt;acceptance criteria&lt;/a&gt;, a base &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects"&gt;Page Object&lt;/a&gt; emerges.&lt;/p&gt;
&lt;em&gt;specifications/src/test/groovy/timezra/course_registry/pages/CourseRegistryPage.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.course_registry.pages&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.apache.commons.lang.StringUtils.splitByCharacterTypeCamelCase&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.WebElement&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.support.FindBy&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.support.PageFactory&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.support.ui.Select&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;abstract&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;CourseRegistryPage&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #464646;"&gt;@FindBy&lt;/span&gt;&lt;span style="color: #000000;"&gt;(className&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"message"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;message&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;T&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;CourseRegistryPage&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;goTo(String&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;address,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Class&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;page)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.get&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;address&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;PageFactory.initElements&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;page&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;CourseRegistryPage(WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.driver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;String&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;title&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;splitByCharacterTypeCamelCase(getClass().simpleName).&lt;/span&gt;&lt;span style="color: #66ccff;"&gt;join&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'&amp;nbsp;'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(!title.equals(driver.title))&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;IllegalStateException(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"Should&amp;nbsp;be&amp;nbsp;on&amp;nbsp;page&amp;nbsp;'${title}'&amp;nbsp;but&amp;nbsp;was&amp;nbsp;on&amp;nbsp;page&amp;nbsp;'${driver.title}'&amp;nbsp;instead"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;methodMissing(String&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;args)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;m&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;((m&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/click_(\w+)/))&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"${m[0][1]}"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement.click()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;PageFactory.initElements&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;args[&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;((m&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/type_(\w+)/))&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"${m[0][1]}"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement.clear()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement.sendKeys&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;args[&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;((m&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/choose_(\w+)/))&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;webElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"${m[0][1]}"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;select&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Select(webElement)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;select.selectByVisibleText&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;args[&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;throw&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;MissingMethodException(name,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;getClass(),&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;args)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;NB: The constructor verifies that the page is correct by comparing the class name to the page title; in addition, the static &lt;em&gt;goTo&lt;/em&gt; method demonstrates how to use the &lt;em&gt;PageFactory&lt;/em&gt; for initializing a &lt;a href="http://code.google.com/p/selenium/wiki/PageObjects"&gt;Page Object&lt;/a&gt;; the &lt;em&gt;methodMissing&lt;/em&gt; declaration also showcases Groovy's ability to call dynamic methods based on the combination of the &lt;em&gt;click&lt;/em&gt;, &lt;em&gt;type&lt;/em&gt; and &lt;em&gt;choose&lt;/em&gt; actions with individual &lt;em&gt;WebElement&lt;/em&gt; names. Such phrases become first-class elements of the testing DSL.&lt;/p&gt;
&lt;p&gt;We can see the use of &lt;em&gt;WebElement&lt;/em&gt; injection and dynamic methods in action with a &lt;em&gt;CreateUser&lt;/em&gt; page that serves as the base for the &lt;em&gt;CreateTeacher&lt;/em&gt; and &lt;em&gt;CreateStudent&lt;/em&gt; pages.&lt;/p&gt;
&lt;em&gt;specifications/src/test/groovy/timezra/course_registry/pages/CreateUser.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.course_registry.pages&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;groovy.transform.InheritConstructors&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.WebDriver&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;org.openqa.selenium.WebElement&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #464646;"&gt;@InheritConstructors&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;abstract&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;CreateUser&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;CourseRegistryPage&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;email&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;password&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebElement&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;create&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;CreateUser(WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;super&lt;/span&gt;&lt;span style="color: #000000;"&gt;(driver)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;T&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;register(name,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;email,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;password,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Class&amp;lt;T&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;nextPage)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type_name&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type_email&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;email&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;type_password&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;password&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;click_create&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;nextPage&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;Other Browsers&lt;/h2&gt;
So far, we have done all our testing with a single &lt;em&gt;WebDriver&lt;/em&gt;, i.e., the &lt;em&gt;FirefoxDriver&lt;/em&gt;. For simple testing, a single driver works fine, but if we wish to ensure that our website works in multiple browsers, we will need to configure our tests to use multiple &lt;em&gt;WebDriver&lt;/em&gt;s. Fortunately, since we are using Gradle to manage our dependencies, the &lt;em&gt;InternetExplorerDriver&lt;/em&gt; and &lt;a href="http://code.google.com/p/selenium/wiki/ChromeDriver" rel="nofollow" title="ChromeDriver" target="_blank"&gt;&lt;em&gt;ChromeDriver&lt;/em&gt;&lt;/a&gt; should be available to us automatically, along with the &lt;em&gt;AndroidDriver&lt;/em&gt; and &lt;em&gt;IPhoneDriver&lt;/em&gt; for testing our application on mobile devices. In addition, an &lt;a href="http://code.google.com/p/selenium/wiki/OperaDriver" rel="nofollow" title="OperaDriver" target="_blank"&gt;OperaDriver&lt;/a&gt; is also available.&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; Some of these drivers require that additional platform-specific software be installed, so please read the project pages for documentation on additional requirements.&lt;/p&gt;
Configuring our specifications to use multiple &lt;em&gt;WebDriver&lt;/em&gt;s should just be a matter of &lt;a href="http://code.google.com/p/spock/wiki/Parameterizations" rel="nofollow" title="parameterizing each Spock feature" target="_blank"&gt;parameterizing each Spock feature&lt;/a&gt;.&lt;br /&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; Unlike JUnit tests which are parameterized by fixture, Spock specifications are parameterized per feature.&lt;/p&gt;
&lt;p&gt;We will modify our &lt;em&gt;TeacherRegistrationSpec&lt;/em&gt; to use the Spock &lt;em&gt;where:&lt;/em&gt; block for parameterization, we will configure multiple &lt;em&gt;WebDriver&lt;/em&gt;s, and we will &lt;em&gt;share&lt;/em&gt; the instance &lt;em&gt;driver&lt;/em&gt; field among the parameterized features.&lt;/p&gt;
&lt;em&gt;timezra/course_registry/TeacherRegistrationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TeacherRegistrationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #464646;"&gt;@Shared&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;setup()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.manage().timeouts().implicitlyWait&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;10&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SECONDS&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;cleanup()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.quit()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;is&amp;nbsp;greeted&amp;nbsp;with&amp;nbsp;an&amp;nbsp;intro&amp;nbsp;screen"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;where:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;browser&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;browsers()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;can&amp;nbsp;register&amp;nbsp;as&amp;nbsp;a&amp;nbsp;teacher"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;where:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;browser&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;browsers()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;browsers()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;System.setProperty(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"webdriver.chrome.driver"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"/path/to/chromedriver"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;drivers&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;[&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;HtmlUnitDriver(),&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;FirefoxDriver(),&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;ChromeDriver()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Browsers(spec:&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;delegate:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;drivers.iterator())&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;final&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Browsers&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #464646;"&gt;@Delegate&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Iterator&amp;lt;WebDriver&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;delegate&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;TeacherRegistrationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spec&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #464646;"&gt;@Override&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;WebDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;next&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;spec.driver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;delegate.&lt;/span&gt;&lt;span style="color: #66ccff;"&gt;next&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;Testing In The Cloud&lt;/h2&gt;
&lt;p&gt;Now that our specifications are running through multiple browsers on a single machine, we can move a step further towards testing multiple browser versions on multiple OSes with cloud-based services such as &lt;a href="http://saucelabs.com/" rel="nofollow" title="Sauce Labs" target="_blank"&gt;Sauce Labs&lt;/a&gt;. For such a powerful service, the configuration changes to our existing application are surprisingly simple. We will modify our &lt;em&gt;TeacherRegistrationSpec&lt;/em&gt; to use a &lt;em&gt;RemoteWebDriver&lt;/em&gt; for the specific browser and OS combination we would like to test along with our Sauce Labs username and API key as described in the &lt;a href="http://saucelabs.com/docs/ondemand/getting-started/env/java/se2/mac" rel="nofollow" title="Sauce OnDemand documentation" target="_blank"&gt;Sauce OnDemand documentation&lt;/a&gt;. We will also need to add a Gradle plugin to start &lt;em&gt;SauceConnect&lt;/em&gt; from the build, just as we start our web application before running acceptance tests. Finally, we should ensure that all references to &lt;em&gt;localhost&lt;/em&gt; in our application are changed to the IP address of the machine where we will be running our tests; otherwise, we might see the &lt;em&gt;SauceConnect&lt;/em&gt; proxy freeze (you might have a different experience, and this freezing might just be attributable to the Gremlins in my machine).&lt;/p&gt;
&lt;em&gt;timezra/course_registry/TeacherRegistrationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TeacherRegistrationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;is&amp;nbsp;greeted&amp;nbsp;with&amp;nbsp;an&amp;nbsp;intro&amp;nbsp;screen"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.get&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://&amp;lt;your.ip.address&amp;gt;:8080/course_registry"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"a&amp;nbsp;user&amp;nbsp;can&amp;nbsp;register&amp;nbsp;as&amp;nbsp;a&amp;nbsp;teacher"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;driver.get&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://&amp;lt;your.ip.address&amp;gt;:8080/course_registry/"&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;protected&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;browsers()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;capabilities&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;DesiredCapabilities.internetExplorer()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;capabilities.setCapability(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"version"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"7"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;capabilities.setCapability(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"platform"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Platform.XP)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;capabilities.setCapability(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;"name"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"Testing&amp;nbsp;Teacher&amp;nbsp;Registration&amp;nbsp;in&amp;nbsp;Sauce"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;sauceDriver&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;RemoteWebDriver(&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;URL(&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"http://&amp;lt;username&amp;gt;:&amp;lt;apiKey&amp;gt;@ondemand.saucelabs.com:80/wd/hub"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;capabilities)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;drivers&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;[sauceDriver]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Browsers(spec:&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;delegate:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;drivers.iterator())&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt; &lt;em&gt;course_registry/specifications/build.gradle&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 1em; background-color: white; border-style: dashed; border-width: thin;"&gt;
&lt;div style="font-family: courier new; width: 80em; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;java.util.concurrent.Executors&lt;/span&gt;&lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;import&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;java.util.concurrent.ExecutorService&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;repositories&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;mavenRepo&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;url:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"https://repository-saucelabs.forge.cloudbees.com/release"&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;dependencies&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;runtime&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;group:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'com.saucelabs'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;name:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'sauce-connect'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;version:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'3.0.18'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;apply&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;plugin:&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SauceConnect&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;sauceConfig&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;username&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'&amp;lt;username&amp;gt;'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;apiKey&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'&amp;lt;apiKey&amp;gt;'&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;test.dependsOn&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;':web:webStart'&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'sauceConnect'&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="color: #000000;"&gt;gradle.taskGraph.afterTask&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Task&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;task,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TaskState&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;state&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;':specifications:test'&lt;/span&gt;&lt;span style="color: #000000;"&gt;.equals(task.path))&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;tasks.getByPath(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'sauceDisconnect'&lt;/span&gt;&lt;span style="color: #000000;"&gt;).execute()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;':web'&lt;/span&gt;&lt;span style="color: #000000;"&gt;).tasks.getByPath(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'webStop'&lt;/span&gt;&lt;span style="color: #000000;"&gt;).execute()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SauceConnect&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;implements&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Plugin&amp;lt;Project&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;ExecutorService&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;executor&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;Executors.newFixedThreadPool(&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;void&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;apply(Project&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;project)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.extensions.sauceConfig&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SauceConnectExtension()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.task(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'sauceConnect'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;output&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;PipedOutputStream()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;input&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;PipedInputStream(output)&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;reader&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;BufferedReader(&lt;/span&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;InputStreamReader(input))&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;executor.execute&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;println&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"Connecting&amp;nbsp;to&amp;nbsp;Sauce&amp;nbsp;Labs&amp;nbsp;as&amp;nbsp;${project.sauceConfig.username}&amp;nbsp;with&amp;nbsp;key&amp;nbsp;${project.sauceConfig.apiKey}...."&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;try&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.javaexec&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;main&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;'com.saucelabs.sauceconnect.SauceConnect'&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;classpath&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.sourceSets.main.runtimeClasspath&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;args&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;[project.sauceConfig.username,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.sauceConfig.apiKey]&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;standardOutput&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;output&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;(Exception&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;ignored)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;Executor&amp;nbsp;has&amp;nbsp;been&amp;nbsp;shutdown&lt;br /&gt; &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;boolean&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;okToStart&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;false&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;executor.execute&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;nextLine&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;try&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;((nextLine&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;reader.readLine())&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;println&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;nextLine&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(!okToStart)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(nextLine&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/Please&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;wait&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;for&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"You&amp;nbsp;may&amp;nbsp;start&amp;nbsp;your&amp;nbsp;tests"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;to&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;start&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;your&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;tests/)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;continue&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(nextLine&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=~&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;/You&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;may&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;start&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;your&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;tests/)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;okToStart&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;true&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;(Exception&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;ignored)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;Executor&amp;nbsp;has&amp;nbsp;been&amp;nbsp;shutdown&lt;br /&gt; &lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(!okToStart)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;Thread.sleep&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;250&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;project.task(&lt;/span&gt;&lt;span style="color: #ff00cc;"&gt;'sauceDisconnect'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;println&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff00cc;"&gt;"Disconnecting&amp;nbsp;from&amp;nbsp;Sauce&amp;nbsp;Labs...."&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;executor.shutdownNow()&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt; &lt;br /&gt; &lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SauceConnectExtension&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;String&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;username&lt;/span&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;String&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;apiKey&lt;/span&gt;&lt;br /&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This post took us through the definition of user stories for a small website, the setup of a Gradle project for automating the website build and the run of its corresponding acceptance tests, the creation of our first &lt;em&gt;WebDriver&lt;/em&gt;-based Spock specification for our acceptance criteria and the fulfillment of that spec with a Grails 2.0 application, the use of Selenium PageObjects to create abstract representations of our web pages before those web pages are even written, all the way to the creation of a Gradle plugin for running our acceptance tests on various browser/OS combinations in Sauce Labs. Each of those items in itself is worthy of a tutorial series. The combination of all these elements demonstrates with a remarkably small amount of configuration and code the type of robust and scalable ATDD infrastructure that is possible and should be at the core of any enterprise web application.&lt;/p&gt;
&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/78219/Agile-Software-Development-BDD-With-Spock-and-Selenium&lt;/span&gt;</description><pubDate>Thu, 02 Feb 2012 16:42:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:78219</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/77604/When-the-bottleneck-of-an-Agile-team-is-the-team-itself#Comments</comments><slash:comments>2</slash:comments><title>When the bottleneck of an Agile team is the team itself</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/77604/When-the-bottleneck-of-an-Agile-team-is-the-team-itself</link><description>&lt;p&gt;by Jayaprakash Puttaswamy&lt;/p&gt;
&lt;p&gt;Most often, we have observed that agile implementations fail in spite of putting efforts towards educating the team about Agile principles, training the team on Agile practices, and getting the right people for Agile roles. Have you ever wondered why? There are chances that the culprit is the team itself.&amp;nbsp; The team could be plagued with several dysfunctions (refer to&amp;nbsp; &amp;ldquo;&lt;a href="http://www.tablegroup.com/books/dysfunctions/" rel="nofollow" title="the five the dysfunctions of team" target="_blank"&gt;the five the dysfunctions of team&lt;/a&gt;&amp;rdquo; model from Patrick Lencioni). If you discover this in your teams, how would you go about dealing with it? How can we overcome the dysfunctions and thus help the team implement agile successfully?&lt;/p&gt;
&lt;p&gt;Well, there are ways to do it. There are instruments and techniques to do it. But all these would fail if you don&amp;rsquo;t have good leadership skills. I would like to share my experience with similar situations, with success stories, challenges and the lessons learnt. Here is a case study which I would describe in three sections:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SITUATION:&lt;b&gt; &lt;/b&gt;Problem statement&lt;/li&gt;
&lt;li&gt;APPROACH:&lt;b&gt; &lt;/b&gt;Key skills used&lt;/li&gt;
&lt;li&gt;SOLUTION:&lt;b&gt; &lt;/b&gt;Results obtained, challenges faced, lessons learnt&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;SITUATION&lt;/h2&gt;
&lt;p&gt;The situation was exactly as outlined below. It was a nine-member team, suffering from dysfunctions (mentioned inside the pyramid). As a result, the team was exhibiting the dysfunctional characteristics (mentioned on right hand side of the pyramid).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.solutionsiq.com/Portals/93486/images/when-the-bottleneck-of-agile-teams-is-the-team-itself.jpg" border="0" alt="when the bottleneck of agile teams is the team itself" class="alignCenter" style="display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Problem statement&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The team was &lt;b&gt;slipping&lt;/b&gt; on deadlines, &lt;b&gt;unable&lt;/b&gt; to fix critical issues and could not removeits&amp;nbsp; &lt;b&gt;high dependency&lt;/b&gt; on two key technical people.&lt;/li&gt;
&lt;li&gt;There were also side effects:
&lt;ul&gt;
&lt;li&gt;Decrease in the &lt;b&gt;morale&lt;/b&gt; of one of the key technical people&lt;/li&gt;
&lt;li&gt;The other key person not being able to focus on &lt;b&gt;continuous improvement&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;APPROACH&lt;/h2&gt;
&lt;p&gt;The team members were trying to follow Scrum as their way of implementing Agile, and there was a technical person who was struggling to play the ScrumMaster role. I had joined this team as a development manager. Irrespective of my role, I had to take charge of the situation to identify the bottleneck. The first thing I did was to take out the teams for a couple of lunch sessions (we decided not to wait for company sponsorship with the budget approval).&lt;/p&gt;
&lt;p&gt;Those sessions, coupled with a team assessment instrument, helped us figure out as a team what the dysfunctions were that were affecting us. The rest was all about leadership skills (refer the inverted pyramid below).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.solutionsiq.com/Portals/93486/images/5-dysfunctions-of-an-agile-scrum-team.jpg" border="0" alt="5 dysfunctions of an agile scrum team" class="alignCenter" style="display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key skills used:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Situational leadership&lt;/li&gt;
&lt;li&gt;Conflict management&lt;/li&gt;
&lt;li&gt;One-on-one feedback&lt;/li&gt;
&lt;li&gt;Time management&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;SOLUTION&lt;/h2&gt;
&lt;p&gt;As a responsible leader, I had to drive the team in a slow and steady manner on the following aspects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Making retrospective meetings effective&lt;/li&gt;
&lt;li&gt;Open &lt;b&gt;evaluation&lt;/b&gt; of team dysfunctions&lt;/li&gt;
&lt;li&gt;Consensus on tackling &amp;ldquo;&lt;b&gt;trust&lt;/b&gt;&amp;rdquo; and &amp;ldquo;&lt;b&gt;conflicts&lt;/b&gt;&amp;rdquo; (which were affecting the team most)&lt;/li&gt;
&lt;li&gt;Enabling the team to &lt;b&gt;share&lt;/b&gt; personal details (strengths and weaknesses)&lt;/li&gt;
&lt;li&gt;Effective sprint planning&lt;/li&gt;
&lt;li&gt;One-on-one discussions between me and other team members&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Results obtained&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;After a period of 6 months of continuous experiments (I call them experiments since there was no single way to address &amp;ldquo;trust&amp;rdquo; and &amp;ldquo;conflict&amp;rdquo; issues), we achieved the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Completion of tasks on-time, with better quality&lt;/li&gt;
&lt;li&gt;Significant reduction of technical dependency on individuals&lt;/li&gt;
&lt;li&gt;Improved &amp;ldquo;self-organizing&amp;rdquo; capability of the team&lt;/li&gt;
&lt;li&gt;Increased morale of the team, as well as the &amp;ldquo;key technical people&amp;rdquo;&lt;/li&gt;
&lt;li&gt;More critical issues were identified and fixed&lt;/li&gt;
&lt;li&gt;The other key technical person got opportunity to improve his &amp;ldquo;leadership&amp;rdquo; skills&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Challenges faced&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Convincing the people on abstract concepts like &amp;ldquo;dysfunctions&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Time management&lt;/li&gt;
&lt;li&gt;Dealing with different personality styles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Lessons learnt&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most of the radical changes require &amp;ldquo;paradigm shifts&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Going first&amp;rdquo; or &amp;ldquo;being vulnerable&amp;rdquo; is the first step&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Constant focus&amp;rdquo; is needed to bring real changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Any successful Agile implementation requires a good leader who can drive the team by identifying dysfunctions, helping the team overcoming them, and facilitating the process of change management if needed. Any of the team members (especially management people) can do this and they should do ONLY this and nothing else. Rest, the team figures itself out. Ending with a quote from Henry Kissinger:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&amp;ldquo;The task of the leader is to get his people from where they are to where they have not been.&amp;rdquo;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/77604/When-the-bottleneck-of-an-Agile-team-is-the-team-itself&lt;/span&gt;</description><pubDate>Tue, 24 Jan 2012 17:01:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:77604</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/77657/Join-us-in-February-at-Agile-India-2012-in-Bangalore#Comments</comments><slash:comments>0</slash:comments><title>Join us in February at Agile India 2012 in Bangalore</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/77657/Join-us-in-February-at-Agile-India-2012-in-Bangalore</link><description>&lt;p&gt;by Pam Dyer&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.solutionsiq.com/course-listings/bid/73604/Agile-India-2012-Bangalore-India-February-17-19" title="Agile India 2012" target="_self"&gt;Agile India 2012&lt;/a&gt;&lt;/strong&gt; is Asia's largest international conference on Agile and Lean software &lt;img id="img-1327011826771" src="http://www.solutionsiq.com/Portals/93486/images/solutionsiq-is-presenting-at-agile-india-2012.jpg" border="0" alt="Join SolutionsIQ at Agile India 2012" class="alignRight" style="float: right;" /&gt;development methods. The conference will held &lt;strong&gt;17th-19th&amp;nbsp;February 2012&lt;/strong&gt; at&amp;nbsp;&lt;strong&gt;&lt;a href="http://www.lemeridien-bangalore.com/" target="_blank"&gt;Le Meridien&lt;/a&gt;, Bangalore, India&lt;/strong&gt;. It offers many sessions from Agile experts, including SolutionsIQ CEO &lt;strong&gt;Charlie Rudd&lt;/strong&gt; and SolutionsIQ Agile Consultant/Coach &lt;strong&gt;William Rowden&lt;/strong&gt;:&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://submit2012india.agilealliance.org/node/8860" rel="nofollow" title="Confronting Business Uncertainty" target="_blank"&gt;&lt;span class="submitted"&gt;Confronting Business Uncertainty&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;span class="submitted"&gt;&lt;strong&gt;Charlie Rudd&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Friday 17 February at 10:45am&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="submitted"&gt;We can never manage uncertainty. Yet in today&amp;rsquo;s business environment we confront it all the time. This talk explains why Agile principles are needed to make good management decisions in an uncertain business environment and why past practices no longer work. We will review what drives business uncertainty and why it&amp;rsquo;s here to stay. We will introduce Agile management principles and explain how they help us navigate uncertainty. We will learn how to use these principles to exploit new business opportunities, reduce business risk and increase returns, while decreasing investment requirements.&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://submit2012india.agilealliance.org/node/8901" rel="nofollow" title="Lean Workflow: A Parable in Pictures" target="_blank"&gt;Lean Workflow: A Parable in Pictures&lt;/a&gt;&lt;/h2&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;William Rowden&lt;/strong&gt;&lt;br /&gt;&lt;span class="submitted"&gt;&lt;span class="submitted"&gt;&lt;strong&gt;&lt;span class="submitted"&gt;Friday 17 February at 10:45am&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;This talk is the tale of two Scrum teams &amp;mdash; team Shu that watched utilization and team Ha that watched lead time &amp;mdash; diagramed on their task boards. Watching work in progress on a task board is sufficient to explain throughput, local sub-optimization, constraints, utilization, efficiency, service time, lead time&amp;mdash;and why even Scrum teams would benefit from a Kanban. Additional maps illustrate wait time, value streams, and wastes. The result is an introduction to Lean, its pillars and principles, primarily in pictures.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://submit2012india.agilealliance.org/node/8865" rel="nofollow" title="Distributed Scrum: Why Some Teams Make it Work Well and Others Don't" target="_blank"&gt;Distributed Scrum: Why Some Teams Make it Work Well and Others Don't&lt;/a&gt;&lt;/h2&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;William Rowden&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Saturday 18 February at 10:45&lt;span class="submitted"&gt;&lt;span class="submitted"&gt;&lt;span class="submitted"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;am&lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;How does a geographically-distributed team collaborate across distance, culture, and even language? What can an organization do to encourage successful teamwork? What technologies and practices increase collaboration? This workshop will explore the patterns that enable companies to successfully deliver software with a distributed team. It will be presented by an Agile coach that assisted with the transition of a company that adopted Agile for teams in three time zones with two languages and cultures, and (travel permitting) the VP Technology of that company.&lt;/p&gt;
&lt;h2&gt;&lt;a href="http://submit2012india.agilealliance.org/node/8861" rel="nofollow" title="Agile Governance" target="_blank"&gt;Agile Governance&lt;/a&gt;&lt;/h2&gt;
&lt;p style="padding-left: 30px;"&gt;&lt;strong&gt;Charlie Rudd&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Saturday 18 February at 3:00pm&lt;/strong&gt;&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;Ironically, conflicts often arise between Agile practitioners and the governance policies of their organizations, even though Agile can provide an excellent (often superior) governance framework. This presentation will explain why these conflicts arise and how they can be resolved. Agile methods will be presented as a governance framework and compared against past practices. Special emphasis will be given to Agile practices as a governance framework for geographically distributed teams.&lt;/p&gt;
&lt;h2&gt;Don't miss this fantastic event!&lt;/h2&gt;
&lt;p&gt;At Agile India 2012, more than 500 participants from all over the world will share their Agile knowledge through presentations, workshops, and tutorials. Twenty-two international research papers from renowned institutes will be presented as well. The full schedule of events is available &lt;a href="http://agile2012.in/program/" rel="nofollow" title="here" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://agile2012.in/" rel="nofollow" title="Learn more and register today!" target="_blank"&gt;&lt;strong&gt;Learn more and register today!&lt;/strong&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/77657/Join-us-in-February-at-Agile-India-2012-in-Bangalore&lt;/span&gt;</description><pubDate>Thu, 19 Jan 2012 21:08:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:77657</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/77019/Reflection-Tools-for-NET#Comments</comments><slash:comments>0</slash:comments><title>Reflection Tools for .NET</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/77019/Reflection-Tools-for-NET</link><description>&lt;p&gt;by Robert Zormeir&lt;/p&gt;
&lt;p&gt;For almost as long as there has been a .NET development environment there have been free &lt;img id="img-1326143791827" src="http://www.solutionsiq.com/Portals/93486/images/net.jpg" border="0" alt="Reflection tools for .NET" width="162" height="104" class="alignRight" style="float: right;" /&gt;developer tools that used Reflection to help developers understand the nature of the beast they were dealing with. The tool that almost everyone started with was .NET Reflector, which was originally written by Lutz Roeder. In 2008, Red Gate Software announced they were taking over future Reflector development, and that Reflector would remain free.&lt;/p&gt;
&lt;p&gt;Early in 2011 Red Gate announced that .NET Reflector would become a paid-for product, and that the free version would no longer be available. They also announced that previously downloaded free versions would time out. After being on the receiving end of what had to be an amazing stream of bile and vitriol due to the idea of reneging on their original promise, they relented and &lt;a href="http://www.reflector.net/2011/04/why-we-reversed-some-of-our-reflector-decision/" rel="nofollow" title="announced" target="_blank"&gt;announced&lt;/a&gt; that previously downloaded versions would be automatically updated to become permanent.&lt;/p&gt;
&lt;p&gt;As we near the one year anniversary of Red Gate's questionable marketing decision, it probably didn't lead to many sales of their paid version, but sudden lack of an established free reflection tool did lead to the creation of several free alternatives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JetBrains &lt;a href="http://www.jetbrains.com/decompiler/" rel="nofollow" title="dotPeek" target="_blank"&gt;dotPeek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;DevExtras &lt;a href="http://www.devextras.com/decompiler/" rel="nofollow" title="CodeReflect" target="_blank"&gt;CodeReflect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.sharpdevelop.net/ilspy.ashx" rel="nofollow" title="ILSpy" target="_blank"&gt;ILSpy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Telerik &lt;a href="http://www.telerik.com/products/decompiler.aspx" rel="nofollow" title="JustDecompile" target="_blank"&gt;JustDecompile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new version of JetBrains dotPeek was released on December 29th and is the cream of the replacement crop so far. It gives you some of the same functionality you'll find in their ReSharper product: The ability to navigate to a specific type, assembly, symbol, or type member; to move between declarations, implementations, derived, and base classes in inheritance chains. It has no installer, so once you download and unpack the ZIP file and you're good to go. DotPeek disassembled my test dll with very good fidelity, but didn't insert curly braces in all the places where I'd like to see them. Maybe a future version will give me the abiltiy to specify code formatting rules the same way ReSharper does. In general, the functionality of dotPeek gives you the idea that you might be in a mini version of Visual Studio.&lt;/p&gt;
&lt;p&gt;DevExtras CodeReflect is available as an MSI installer or a ZIP file. It was quick to download and unpack. It performed well, but didn't do the full colorization of the code the way dotPeek and JustDecompile did. One nice feature is that it allows you to quickly switch back and forth between MSIL, C#, and VB.NET code. The decompilation fidelity was good, but it did generate some intermediate variables that didn't exist in the original code.&lt;/p&gt;
&lt;p&gt;LSpy is an open-source project that requires .NET Framework 4.0. You can download the binaries or the source code from SourceForge. The program will check for updates once a week if you prefer. The performance was good, and the decompilation fidelity was very good, but the code colorization was a little weird. But I can live with that. You can quickly switch back and forth between generating MSIL and C# code.&lt;/p&gt;
&lt;p&gt;The installer for Telerik JustComplile asks for too much registration info and takes too long to do its work, IMHO. Telerik appears to be viewing their product as too much of a marketing opportunity... to the point that it ceases to be a marketing opportunity with me. You'll see "Just kick back and relax. Good things take time. Please be patient." as the installation proceeds. You also need to be patient as the the installed program goes through the process of "Loading assemblies." JustDecompile had a bit of trouble with decompiling a relatively simple class, but it did come close and the software is still in beta. Once everything was loaded the performance seemed very good.&lt;/p&gt;
&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/77019/Reflection-Tools-for-NET&lt;/span&gt;</description><pubDate>Thu, 12 Jan 2012 13:05:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:77019</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/76751/Mocking-Frameworks-for-NET#Comments</comments><slash:comments>0</slash:comments><title>Mocking Frameworks for .NET</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/76751/Mocking-Frameworks-for-NET</link><description>&lt;p&gt;by Robert Zormeir&lt;/p&gt;
&lt;p&gt;The four major competitors in the free/open source .NET mocking framework arena are &lt;img id="img-1325705498971" src="http://www.solutionsiq.com/Portals/93486/images/net.jpg" border="0" alt="microsoft .net" width="173" height="111" class="alignRight" style="float: right;" /&gt;NMock/NMock2, NMock3, Rhino Mocks and MOQ. NMock and NMock2 were actually built by different teams, but they kept the same design philosophy and are backwards compatible so they can be used almost interchangeably. If you're familiar with NMock/NMock2, you'll see that NMock3 is from the same gene pool, but it starts fresh and has somewhat different syntax from its siblings. All of the major mocking libraries are mature products with a decent-sized user base, so it's not tough to find good examples and help for all of them but NMock3.&lt;/p&gt;
&lt;p&gt;Like many other .NET developers, I started using NMock, and then "upgraded' to nMock2, but both use "magic strings" which can't take advantage of Intellisense, and make tests brittle because they're not easily amenable to refactoring without the use of additional tools like ReSharper to replace name-similar text in strings. On the plus side, NMock doesn't rely on the explicit record/replay statements as Rhino Mocks does. The NMock2 codebase hasn't been updated since late in 2009, and should not be expected to see continued development.&lt;/p&gt;
&lt;p&gt;On the plus side, Rhino Mocks has a syntax that supports code refactoring and compile-time checking. Unfortunately, I don't find the syntax to be particularly intuitive, and the variety of ways to construct and condition mocks can lead to some confusion when different people are writing tests. There is also the annoying need to write explicit record and replay statements. Another problem with Rhino Mocks is that the project appears to be running out of steam. Aside from a few bug-fix patches, not much has happened since early in 2009.&lt;/p&gt;
&lt;p&gt;MOQ is one of the new kids, with an annoying name that needs to be spelled out so that people know what you're talking about. The latest release became available in April of 2011, and MOQ has active developers and community. It's different from the first two in several ways. When using NMock and Rhino you create mock objects of a specific type. When using MOQ you create mocks that contain an objects of a specific type, and that wrapper around the mock objects lends itself to simpler syntax in your tests. MOQ requires .Net 3.5 or greater due to its use of lambdas, so if you haven't learned to use lambda expressions, now is the time. I haven't used it extensively, but so far I like everything about MOQ... except for the name.&lt;/p&gt;
&lt;p&gt;NMock3 is the other new kid, and the one who seems less well known. Maybe it isn't on the radar for most folks because NMock/NMock2 seem behind the times, and that may have kept expectations low. Versions of NMock3 are available for .NET 3.5 and 4.0, and the latest RTM became available in January of 2011 with a beta release in July of 2011. Like MOQ, you create mocks that contain objects of a specific type, and that wrapper around the mock objects leverages lambda expressions, so NMock/NMock2 users are in for some culture shock. Since the NMock3 examples are a little thin in the wild I've include sample code below. Note that in conditioning your mocks, the parameters in the lambda expressions are just placeholders, while the "real" parameters are specified in the "With" method.&lt;/p&gt;
&lt;div class="code"&gt;&lt;span style="color: blue;"&gt;using&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;NUnit.Framework&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; using&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;NMock&lt;/span&gt;&lt;span style="color: blue;"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkgreen;"&gt;/*&amp;nbsp;NMock3&amp;nbsp;*/&lt;br /&gt; &lt;br /&gt; &lt;/span&gt;&lt;span style="color: blue;"&gt;namespace&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Foo.Test&lt;br /&gt; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;TestFixture&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;FundsTransferPresenterTest&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;MockFactory&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;_mocks&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;Mock&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IFundsTransferView&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;_viewMock&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;Mock&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IAccountService&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;_serviceMock&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;FundsTransferPresenter&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;_presenter&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;SetUp&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;void&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;SetUp()&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_mocks&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;MockFactory()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_viewMock&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_mocks.CreateMock&amp;lt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IFundsTransferView&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_serviceMock&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_mocks.CreateMock&amp;lt;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IAccountService&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_presenter&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;new&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;FundsTransferPresenter(_viewMock.MockObject,&amp;nbsp;_serviceMock.MockObject)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;Test&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;void&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;CanQueryViewUseAccountServiceToFundsTransfer()&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_viewMock.Expects.One.Method(v&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;v.GetSourceAccount()).WillReturn(&lt;/span&gt;&lt;span style="color: #606060;"&gt;"1234"&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_viewMock.Expects.One.GetProperty(v&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;v.TargetAccount).WillReturn(&lt;/span&gt;&lt;span style="color: #606060;"&gt;"9876"&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_viewMock.Expects.One.GetProperty(v&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;v.TransferAmount).WillReturn(&lt;/span&gt;&lt;span style="color: maroon;"&gt;200.00m&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_serviceMock.Expects.Exactly(&lt;/span&gt;&lt;span style="color: maroon;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;).Method(s&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;gt;&amp;nbsp;s.TransferFunds(&lt;/span&gt;&lt;span style="color: blue;"&gt;null&lt;/span&gt;&lt;span style="color: black;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;null&lt;/span&gt;&lt;span style="color: black;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: maroon;"&gt;0m&lt;/span&gt;&lt;span style="color: black;"&gt;)).With(&lt;/span&gt;&lt;span style="color: #606060;"&gt;"1234"&lt;/span&gt;&lt;span style="color: black;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #606060;"&gt;"9876"&lt;/span&gt;&lt;span style="color: black;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: maroon;"&gt;200.00m&lt;/span&gt;&lt;span style="color: black;"&gt;)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_presenter.Transfer_Clicked()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_mocks.VerifyAllExpectationsHaveBeenMet()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span style="color: darkgreen;"&gt;/******************************* &amp;nbsp; Fragment of System Under Test (SUT) &amp;nbsp; *******************************&lt;/span&gt;/&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;interface&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IFundsTransferView&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;GetSourceAccount()&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;TargetAccount&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;get;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;decimal&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;TransferAmount&amp;nbsp;{&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;get;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;interface&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IAccountService&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;void&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;TransferFunds(&lt;/span&gt;&lt;span style="color: blue;"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;source,&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;string&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;target,&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;decimal&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;amount)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;class&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;FundsTransferPresenter&lt;/span&gt;&lt;span style="color: black;"&gt;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IFundsTransferView&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;_view&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IAccountService&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;_service&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;&lt;/span&gt;&lt;span&gt;FundsTransferPresenter(&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IFundsTransferView&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;view,&amp;nbsp;&lt;/span&gt;&lt;span style="color: darkcyan;"&gt;IAccountService&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;nbsp;service)&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_service&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;service&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;_view&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;view&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue;"&gt;public&amp;nbsp;void&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;Transfer_Clicked()&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_service.TransferFunds(_view.GetSourceAccount(),&amp;nbsp;_view.TargetAccount,&amp;nbsp;_view.TransferAmount)&lt;/span&gt;&lt;span style="color: blue;"&gt;;&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: black;"&gt;}&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; &lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/76751/Mocking-Frameworks-for-NET&lt;/span&gt;</description><pubDate>Wed, 04 Jan 2012 19:07:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:76751</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/75796/Use-It-Testing-in-Agile-Software-Development#Comments</comments><slash:comments>0</slash:comments><title>Use-It Testing in Agile Software Development</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/75796/Use-It-Testing-in-Agile-Software-Development</link><description>&lt;p&gt;by Dan Ebert&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agile Coach&lt;/strong&gt;: &amp;ldquo;What kind of testing do the developers do?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Development Team Member&lt;/strong&gt;: &amp;ldquo;First we create some test data if needed. Then we go to the web page and use the feature to make sure it works.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I call this anti-pattern &amp;ldquo;Use-It Testing.&amp;rdquo; I&amp;rsquo;m always surprised, and disappointed, when I encounter a team that relies solely on Use-It Testing when writing their code.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d bet everyone who&amp;rsquo;s written a line of code has done it at least once. You write a bit of code &amp;hellip; then use it by running the program, going to the web page, etc. to see if it works. This *might* be OK for prototyping (I&amp;rsquo;m sure there are some who would argue that Use-It Testing is not sufficient even when prototyping) but it is definitely not sufficient for production work.&lt;/p&gt;
&lt;p&gt;There are three main types of testing typically done by an Agile Team: Unit Testing, &lt;img src="http://www.solutionsiq.com/Portals/93486/images/use-it-testing-in-agile-software-development.gif" border="0" alt="use it testing in agile software development" class="alignRight" style="float: right;" /&gt;Integration Testing, and Functional Testing. All should be automated so they can be run frequently with little effort.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Unit Tests&lt;/b&gt; are the finest grained. The units under test should be very small, just a few lines of code, and are often written the same time as the production code. They isolate the code under test from all other components by using &lt;a&gt;Test Doubles&lt;/a&gt; if necessary. There should be more Unit Tests than any other kind of test because they cover all paths through the code. Due to the quantity, these tests must execute quickly so they can be run frequently to provide feedback during development. They also provide the safety net when refactoring and changing functionality.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Integration Tests&lt;/b&gt; test the interaction between two components: testing a DAO&amp;rsquo;s (Data Access Object) interaction with the database, testing a client against a web service, etc. Fewer Integration Tests are needed because they don&amp;rsquo;t need to cover every path (Unit Tests are responsible for that); testing a few paths is sufficient to assert the integration works. Integration Tests usually take longer to run, but this is OK since there are fewer tests to run.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Functional Tests&lt;/b&gt; can be broken down into many categories: Acceptance Tests, UI Tests, End-to-End Tests, etc. These test the whole system, are usually the slowest running, and should be the fewest in number. They are good at detecting environment issues and testing the interaction of multiple components.&lt;/p&gt;
&lt;p&gt;In addition to these automated tests, most teams do some Exploratory Testing as well. This *is* using the application &amp;hellip; but with the main goals of assessing usability and finding features/behaviors which were missed. These findings often result in new stories for the backlog. Of course, bugs can be found during this testing. The appropriate (failing) test should be written, then code fixed, then the test run and the featured exercised to verify the fix.&lt;/p&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/75796/Use-It-Testing-in-Agile-Software-Development&lt;/span&gt;</description><pubDate>Thu, 15 Dec 2011 20:13:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:75796</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/75478/Developing-Eclipse-Plug-ins-Program-to-Publish#Comments</comments><slash:comments>0</slash:comments><title>Developing Eclipse Plug-ins: Program to Publish</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/75478/Developing-Eclipse-Plug-ins-Program-to-Publish</link><description>&lt;p&gt;by Tim Myer&lt;/p&gt;
&lt;h2&gt;Goal&lt;/h2&gt;
The purpose of this blog entry is to demonstrate one workflow for taking an idea for an Eclipse plug-in from concept to product downloadable from the Eclipse marketplace.&lt;br /&gt;
&lt;h4&gt;tl;dr&lt;/h4&gt;
If you want to look right away at working code for a simple Eclipse plug-in, feature, update site and their &lt;a href="http://www.eclipse.org/tycho/" rel="nofollow" title="Tycho" target="_blank"&gt;Tycho&lt;/a&gt; configurations, a &lt;a href="https://github.com/timezra/save-actions-extensions" rel="nofollow" title="sample project" target="_blank"&gt;sample project&lt;/a&gt; based on this tutorial is available. The plug-in can also be installed in Eclipse through the &lt;a href="http://marketplace.eclipse.org" rel="nofollow" title="Marketplace" target="_blank"&gt;Marketplace&lt;/a&gt; (search for "save actions") or directly from an &lt;a href="http://timezra.github.com/save-actions-extensions/" rel="nofollow" title="update site" target="_blank"&gt;update site&lt;/a&gt;. In addition, the conventions for project setup contained in this tutorial have been extracted into &lt;a href="https://github.com/timezra/tycho_new_plugin_project" rel="nofollow" title="a Maven archetype" target="_blank"&gt;a Maven archetype&lt;/a&gt;. Since this blog entry does not provide an in-depth introduction to the nuances of configuring and writing Eclipse plug-ins, having the project source as a reference, either locally or in a web browser, will be helpful for following the examples.&lt;br /&gt;
&lt;h2&gt;The Idea&lt;/h2&gt;
&lt;p&gt;Suppose we are starting a new project on an existing codebase and, as part of our Working Agreement, the team has decided to automate certain coding standards with Eclipse Java editor save actions. It would be convenient to bring all the existing code up to our standards before development even begins. Currently, formatting and import organization can be performed in bulk from the source submenu in the workbench. Eclipse users can also apply clean-up conventions from this submenu. Unfortunately, even though the clean-up and save participants have similar configurations, there is a disconnect between the two.&lt;/p&gt;
&lt;p&gt;Exposing save actions for the bulk processing of Java/Groovy files through this source submenu is a simple enough feature to add to Eclipse and should provide the opportunity to experience one full cycle of Eclipse plug-in development, from the creation of a simple plug-in and its integration tests, to the addition of a feature to contain the plug-in, to the packaging of an update site, to the distribution of the product through the &lt;a href="http://marketplace.eclipse.org" rel="nofollow" title="Eclipse Marketplace" target="_blank"&gt;Eclipse Marketplace&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Plug-in&lt;/h2&gt;
We will begin by creating a new plug-in project named &lt;em&gt;timezra.eclipse.apply_save_actions&lt;/em&gt; in our Eclipse workspace. Since we will eventually generate a Tycho configuration in order to automate the compilation, testing and packaging of our product, we will modify a few of the default settings for the plug-in. Our plug-in and fragment projects will be contained in a &lt;em&gt;plugins&lt;/em&gt; subdirectory, here &lt;em&gt;/path/to/workspace/plugins/timezra.eclipse.apply_save_actions&lt;/em&gt;. Our source folder will be &lt;em&gt;src/main/java&lt;/em&gt; and output folder will be &lt;em&gt;target/classes&lt;/em&gt; to follow the Maven convention.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm7.static.flickr.com/6110/6236573817_b280ed1379_z.jpg" alt="The New Plug-in Project wizard with Maven-inspired configurations" /&gt;&lt;br /&gt;&lt;br /&gt;We can either use the New Plug-in Project Wizard &lt;em&gt;Hello, World Command Template&lt;/em&gt; or we can contribute a command to a menu with manual configuration. There are already quite a &lt;a href="http://my.safaribooksonline.com/book/software-engineering-and-development/ide/9780321574435/commands-and-actions/ch06lev1sec1" rel="nofollow" title="few" target="_blank"&gt;few&lt;/a&gt; &lt;a href="http://help.eclipse.org/indigo/index.jsp?topic=http://www.solutionsiq.com/org.eclipse.platform.doc.isv/guide/workbench_cmd_handlers.htm" rel="nofollow" title="resources" target="_blank"&gt;resources&lt;/a&gt; &lt;a href="http://www.eclipse-tips.com/tutorials/1-actions-vs-commands" rel="nofollow" title="for" target="_blank"&gt;for&lt;/a&gt; &lt;a href="http://wiki.eclipse.org/Platform_Command_Framework" rel="nofollow" title="contributing" target="_blank"&gt;contributing&lt;/a&gt; &lt;a href="http://www.vogella.de/articles/EclipseCommands/article.html" rel="nofollow" title="commands" target="_blank"&gt;commands&lt;/a&gt; through an extension point, so you can get more insight into specific configuration settings there.&lt;br /&gt;For this example, the configuration is boilerplate. The internals of the ApplySaveActions command handler are somewhat interesting. There may be a more direct way to invoke the save participant, but this method works on both un-opened files and source buffers modified in memory for Java and Groovy, so in the interest of &lt;a href="http://www.xprogramming.com/Practices/PracSimplest.html" rel="nofollow" title="DTSTTCPW" target="_blank"&gt;DTSTTCPW&lt;/a&gt;, we can use this simple implementation until it is no longer sufficient.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;plugins/timezra.eclipse.apply_save_actions/src/main/java/timezra/eclipse/apply_save_actions/handlers/ApplySaveActions.java&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;package&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;timezra.eclipse.apply_save_actions.handlers;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.Arrays.asList;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.lang.reflect.InvocationTargetException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.ArrayList;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.Collection;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.commands.AbstractHandler;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.commands.ExecutionEvent;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.commands.ExecutionException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IFile;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IWorkspace;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.ResourcesPlugin;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.CoreException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.IAdapterManager;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.IProgressMonitor;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.OperationCanceledException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.Platform;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.ICompilationUnit;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IJavaElement;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IJavaProject;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IPackageFragment;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IPackageFragmentRoot;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.JavaModelException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jface.operation.IRunnableWithProgress;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jface.viewers.ISelection;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jface.viewers.IStructuredSelection;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.IWorkbench;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.PlatformUI;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.actions.WorkspaceModifyOperation;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.handlers.HandlerUtil;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.part.FileEditorInput;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.texteditor.IDocumentProvider;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;extends&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;AbstractHandler&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IAdapterManager&amp;nbsp;adapterManager;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IWorkspace&amp;nbsp;workspace;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IWorkbench&amp;nbsp;workbench;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;(Platform.getAdapterManager(),&amp;nbsp;ResourcesPlugin.getWorkspace(),&amp;nbsp;PlatformUI.getWorkbench());&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ApplySaveActions(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IAdapterManager&amp;nbsp;adapterManager,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IWorkspace&amp;nbsp;workspace,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IWorkbench&amp;nbsp;workbench)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.adapterManager&amp;nbsp;=&amp;nbsp;adapterManager;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.workspace&amp;nbsp;=&amp;nbsp;workspace;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.workbench&amp;nbsp;=&amp;nbsp;workbench;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object&amp;nbsp;execute(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionEvent&amp;nbsp;event)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ISelection&amp;nbsp;currentSelection&amp;nbsp;=&amp;nbsp;HandlerUtil.getCurrentSelectionChecked(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(currentSelection&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;instanceof&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IStructuredSelection)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IStructuredSelection&amp;nbsp;selections&amp;nbsp;=&amp;nbsp;(IStructuredSelection)&amp;nbsp;currentSelection;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(selections);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;JavaModelException&amp;nbsp;e)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException(Messages.APPLY_SAVE_ACTIONS_UNEXPECTED_ERROR,&amp;nbsp;e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;InvocationTargetException&amp;nbsp;e)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException(Messages.APPLY_SAVE_ACTIONS_UNEXPECTED_ERROR,&amp;nbsp;e.getTargetException());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applyTo(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IStructuredSelection&amp;nbsp;selections)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;JavaModelException,&amp;nbsp;InvocationTargetException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object&amp;nbsp;o&amp;nbsp;:&amp;nbsp;selections.toList())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IJavaProject&amp;nbsp;javaProject&amp;nbsp;=&amp;nbsp;getAdapter(o,&amp;nbsp;IJavaProject.&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(javaProject&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(javaProject.getPackageFragments());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragmentRoot&amp;nbsp;packageFragmentRoot&amp;nbsp;=&amp;nbsp;getAdapter(o,&amp;nbsp;IPackageFragmentRoot.&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(packageFragmentRoot&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(packageFragmentRoot);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragment&amp;nbsp;packageFragment&amp;nbsp;=&amp;nbsp;getAdapter(o,&amp;nbsp;IPackageFragment.&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(packageFragment&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(packageFragment);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit&amp;nbsp;compilationUnit&amp;nbsp;=&amp;nbsp;getAdapter(o,&amp;nbsp;ICompilationUnit.&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(compilationUnit&amp;nbsp;!=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(compilationUnit);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;continue&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applyTo(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragmentRoot&amp;nbsp;packageFragmentRoot)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;JavaModelException,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InvocationTargetException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IJavaElement[]&amp;nbsp;children&amp;nbsp;=&amp;nbsp;packageFragmentRoot.getChildren();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragment[]&amp;nbsp;fragments&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragment[children.length];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.arraycopy(children,&amp;nbsp;0,&amp;nbsp;fragments,&amp;nbsp;0,&amp;nbsp;children.length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(fragments);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applyTo(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragment...&amp;nbsp;packageFragments)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;JavaModelException,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InvocationTargetException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Collection&amp;lt;ICompilationUnit&amp;gt;&amp;nbsp;compilationUnits&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ArrayList&amp;lt;ICompilationUnit&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IPackageFragment&amp;nbsp;f&amp;nbsp;:&amp;nbsp;packageFragments)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compilationUnits.addAll(asList(f.getCompilationUnits()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(compilationUnits.toArray(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit[compilationUnits.size()]));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applyTo(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit...&amp;nbsp;compilationUnits)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;InvocationTargetException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IRunnableWithProgress&amp;nbsp;delegate&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActionsOperation(compilationUnits);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;workbench.getProgressService().run(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;delegate);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;catch&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;InterruptedException&amp;nbsp;e)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;cancellation&amp;nbsp;is&amp;nbsp;fine&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@SuppressWarnings(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"restriction"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IDocumentProvider&amp;nbsp;createDocumentProvider()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitDocumentProvider();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@SuppressWarnings(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"unchecked"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;lt;T&amp;gt;&amp;nbsp;T&amp;nbsp;getAdapter(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object&amp;nbsp;o,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Class&amp;lt;T&amp;gt;&amp;nbsp;c)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(T)&amp;nbsp;adapterManager.getAdapter(o,&amp;nbsp;c);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActionsOperation&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;extends&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;WorkspaceModifyOperation&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit[]&amp;nbsp;compilationUnits;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ApplySaveActionsOperation(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit...&amp;nbsp;compilationUnits)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.compilationUnits&amp;nbsp;=&amp;nbsp;compilationUnits;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;execute(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProgressMonitor&amp;nbsp;pm)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pm.beginTask(Messages.APPLY_SAVE_ACTIONS_BEGIN_TASK,&amp;nbsp;compilationUnits.length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ICompilationUnit&amp;nbsp;unit&amp;nbsp;:&amp;nbsp;compilationUnits)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applyTo(workspace.getRoot().getFile(unit.getPath()),&amp;nbsp;pm);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;finally&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pm.done();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applyTo(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFile&amp;nbsp;f,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProgressMonitor&amp;nbsp;pm)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;report(f.getName(),&amp;nbsp;pm);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IDocumentProvider&amp;nbsp;provider&amp;nbsp;=&amp;nbsp;createDocumentProvider();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FileEditorInput&amp;nbsp;editorInput&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;FileEditorInput(f);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;provider.connect(editorInput);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;provider.aboutToChange(editorInput);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;provider.saveDocument(pm,&amp;nbsp;editorInput,&amp;nbsp;provider.getDocument(editorInput),&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;finally&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;provider.changed(editorInput);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;provider.disconnect(editorInput);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;report(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;task,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProgressMonitor&amp;nbsp;pm)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(pm.isCanceled())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;OperationCanceledException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pm.setTaskName(task);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pm.worked(1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;The Test Fragment&lt;/h2&gt;
&lt;p&gt;We will similarly create a new integration test fragment alongside this plug-in, overriding the default configuration to store the fragment into the &lt;em&gt;plugins&lt;/em&gt; subdirectory and to use Maven conventions for the source and output directories.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm7.static.flickr.com/6211/6236573901_762ff9c69f_z.jpg" alt="The New Fragment Project wizard with Maven-inspired configurations" /&gt;&lt;br /&gt;&lt;br /&gt;There are &lt;a href="http://www.modumind.com/2007/06/20/unit-testing-plug-ins-with-fragments/" rel="nofollow" title="various approaches" target="_blank"&gt;various approaches&lt;/a&gt; for testing Eclipse plug-ins, but the fragment approach has been &lt;a href="http://wiki.eclipse.org/Tycho/Packaging_Types#eclipse-test-plugin" rel="nofollow" title="embraced by the Tycho community" target="_blank"&gt;embraced by the Tycho community&lt;/a&gt;, so we will use it here.&lt;br /&gt;Again, the project configuration can be boilerplate for now. Of particular interest is the handler test case.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;plugins/timezra.eclipse.apply_save_actions.tests/src/test/java/timezra/eclipse/apply_save_actions/handlers/ApplySaveActions.java&lt;/em&gt;&lt;/p&gt;
&lt;div style="overflow: auto; height: 1200x; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;package&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;timezra.eclipse.apply_save_actions.handlers;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.Assert.assertEquals;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.Assert.assertNull;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.io.ByteArrayInputStream;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.io.IOException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.ArrayList;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.Collections;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.HashMap;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.List;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.Map;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;java.util.Scanner;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.commands.ExecutionEvent;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.commands.ExecutionException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.expressions.EvaluationContext;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IContainer;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IFile;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IFolder;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IProject;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IResource;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.IWorkspaceRoot;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.resources.ResourcesPlugin;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.CoreException;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.IProgressMonitor;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.NullProgressMonitor;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.Path;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.SubProgressMonitor;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.core.runtime.preferences.InstanceScope;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IClasspathEntry;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.IJavaProject;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.core.JavaCore;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.launching.JavaRuntime;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.ui.JavaUI;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jdt.ui.cleanup.CleanUpOptions;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jface.text.TextSelection;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.jface.viewers.StructuredSelection;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.eclipse.ui.ISources;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.After;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.Before;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.Rule;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.Test;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.junit.rules.MethodRule;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;timezra.eclipse.apply_save_actions.Constants;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;timezra.eclipse.apply_save_actions.tests.ModifiesSaveActionsPreferences;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;timezra.eclipse.apply_save_actions.tests.ModifiesSaveActionsPreferencesRule;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActionsPluginTest&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;SOURCE_FOLDER&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"src/test/java"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;EOL&amp;nbsp;=&amp;nbsp;System.getProperty(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"line.separator"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProgressMonitor&amp;nbsp;NULL_PROGRESS_MONITOR&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;NullProgressMonitor();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;TEST_CLASS&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"TestClass"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;TEST_PACKAGE&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"timezra.eclipse.apply_save_actions"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;TEST_CLASS_BEFORE_SAVE_ACTIONS&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"package&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_PACKAGE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;";import&amp;nbsp;java.util.*;class&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"{private&amp;nbsp;List&amp;lt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;gt;&amp;nbsp;l;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"(List&amp;lt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;gt;&amp;nbsp;l){this.l=l;}}"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;TEST_CLASS_AFTER_SAVE_ACTIONS&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"package&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_PACKAGE&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;";"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"import&amp;nbsp;java.util.List;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"class&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;nbsp;{"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;nbsp;&amp;nbsp;private&amp;nbsp;final&amp;nbsp;List&amp;lt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;gt;&amp;nbsp;l;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;nbsp;&amp;nbsp;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"(List&amp;lt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;gt;&amp;nbsp;l)&amp;nbsp;{"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.l&amp;nbsp;=&amp;nbsp;l;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"&amp;nbsp;&amp;nbsp;}"&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;+&amp;nbsp;EOL&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"}"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Rule&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;MethodRule&amp;nbsp;rule&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ModifiesSaveActionsPreferencesRule();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProject&amp;nbsp;aJavaProject;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaPackage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFile&amp;nbsp;aJavaFile;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaSourceFolder;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Before&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;setUp()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaProject&amp;nbsp;=&amp;nbsp;createAJavaProject(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"a_java_project"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaSourceFolder&amp;nbsp;=&amp;nbsp;createASourceFolder(SOURCE_FOLDER);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaPackage&amp;nbsp;=&amp;nbsp;createAPackage(aJavaSourceFolder,&amp;nbsp;TEST_PACKAGE.replaceAll(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"\\."&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"/"&lt;/span&gt;&lt;span style="color: #000000;"&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaFile&amp;nbsp;=&amp;nbsp;createAJavaFile(aJavaPackage,&amp;nbsp;TEST_CLASS&amp;nbsp;+&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;".java"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@After&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;tearDown()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaProject.delete(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;NULL_PROGRESS_MONITOR);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;theCurrentSelectionMustBeStructured()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions&amp;nbsp;command&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;EvaluationContext&amp;nbsp;context&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;EvaluationContext(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;context.addVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TextSelection(0,&amp;nbsp;100));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionEvent&amp;nbsp;event&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionEvent(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;Collections.emptyMap(),&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;context);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertNull(command.execute(event));&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;@ModifiesSaveActionsPreferences&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaFileCanBeReformatted()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException,&amp;nbsp;CoreException,&amp;nbsp;IOException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enableJavaSaveActions();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applySaveActions(JavaCore.create(aJavaFile));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verifyThatSaveActionsHaveBeenApplied(aJavaFile);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;@ModifiesSaveActionsPreferences&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaPackageCanBeReformatted()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException,&amp;nbsp;CoreException,&amp;nbsp;IOException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enableJavaSaveActions();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applySaveActions(JavaCore.create(aJavaPackage));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verifyThatSaveActionsHaveBeenApplied(aJavaFile);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;@ModifiesSaveActionsPreferences&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaSourceFolderCanBeReformatted()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException,&amp;nbsp;CoreException,&amp;nbsp;IOException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enableJavaSaveActions();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applySaveActions(JavaCore.create(aJavaSourceFolder));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verifyThatSaveActionsHaveBeenApplied(aJavaFile);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;@ModifiesSaveActionsPreferences&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaProjectCanBeReformatted()&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException,&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;enableJavaSaveActions();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;applySaveActions(JavaCore.create(aJavaProject));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verifyThatSaveActionsHaveBeenApplied(aJavaFile);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;applySaveActions(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object&amp;nbsp;selection)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions&amp;nbsp;command&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ApplySaveActions();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;EvaluationContext&amp;nbsp;context&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;EvaluationContext(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Object());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;context.addVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;StructuredSelection(selection));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionEvent&amp;nbsp;event&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ExecutionEvent(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;Collections.emptyMap(),&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;context);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command.execute(event);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;contains&amp;nbsp;a&amp;nbsp;beaut&amp;nbsp;that&amp;nbsp;turns&amp;nbsp;a&amp;nbsp;stream&amp;nbsp;into&amp;nbsp;a&amp;nbsp;String&amp;nbsp;without&amp;nbsp;using&amp;nbsp;IoUtils:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;http://stackoverflow.com/questions/309424/in-java-how-do-a-read-convert-an-inputstream-in-to-a-string&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;verifyThatSaveActionsHaveBeenApplied(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFile&amp;nbsp;aJavaFile)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;actualContents;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Scanner&amp;nbsp;scanner&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Scanner(aJavaFile.getContents());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;try&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;actualContents&amp;nbsp;=&amp;nbsp;scanner.useDelimiter(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"\\A"&lt;/span&gt;&lt;span style="color: #000000;"&gt;).next();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;finally&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scanner.close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertEquals(TEST_CLASS_AFTER_SAVE_ACTIONS,&amp;nbsp;actualContents);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;@SuppressWarnings(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"restriction"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;enableJavaSaveActions()&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InstanceScope.INSTANCE.getNode(JavaUI.ID_PLUGIN).putBoolean(Constants.PERFORM_SAVE_ACTIONS_PREFERENCE,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Map&amp;lt;String,&amp;nbsp;String&amp;gt;&amp;nbsp;cleanupPreferences&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;HashMap&amp;lt;String,&amp;nbsp;String&amp;gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.eclipse.jdt.internal.ui.JavaPlugin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.getDefault()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.getCleanUpRegistry()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.getDefaultOptions(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.eclipse.jdt.internal.corext.fix.CleanUpConstants.DEFAULT_SAVE_ACTION_OPTIONS)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.getMap());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleanupPreferences.put(org.eclipse.jdt.internal.corext.fix.CleanUpConstants.FORMAT_SOURCE_CODE,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CleanUpOptions.TRUE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleanupPreferences.put(org.eclipse.jdt.internal.corext.fix.CleanUpConstants.ORGANIZE_IMPORTS,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CleanUpOptions.TRUE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleanupPreferences.put(org.eclipse.jdt.internal.corext.fix.CleanUpConstants.CLEANUP_ON_SAVE_ADDITIONAL_OPTIONS,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CleanUpOptions.TRUE);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.eclipse.jdt.internal.corext.fix.CleanUpPreferenceUtil.saveSaveParticipantOptions(InstanceScope.INSTANCE,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleanupPreferences);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;createASourceFolder(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;name)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaSourceFolder&amp;nbsp;=&amp;nbsp;aJavaProject.getFolder(Path.fromPortableString(name));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create(aJavaSourceFolder);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaSourceFolder;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;createAPackage(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaSourceFolder,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;name)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaPackage&amp;nbsp;=&amp;nbsp;aJavaSourceFolder.getFolder(Path.fromPortableString(name));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create(aJavaPackage);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaPackage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;create(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;folder)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IContainer&amp;nbsp;parent&amp;nbsp;=&amp;nbsp;folder.getParent();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(parent.getType()&amp;nbsp;==&amp;nbsp;IResource.FOLDER&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!parent.exists())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create((IFolder)&amp;nbsp;parent);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;folder.create(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;NULL_PROGRESS_MONITOR);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFile&amp;nbsp;createAJavaFile(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFolder&amp;nbsp;aJavaPackage,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;name)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IFile&amp;nbsp;aJavaFile&amp;nbsp;=&amp;nbsp;aJavaPackage.getFile(Path.fromPortableString(name));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;aJavaFile.create(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ByteArrayInputStream(TEST_CLASS_BEFORE_SAVE_ACTIONS.getBytes()),&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL_PROGRESS_MONITOR);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;aJavaFile;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f7f5f;"&gt;//&amp;nbsp;based&amp;nbsp;on&amp;nbsp;http://www.stateofflow.com/journal/66/creating-java-projects-programmatically&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;@SuppressWarnings(&lt;/span&gt;&lt;span style="color: #2a00ff;"&gt;"restriction"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProject&amp;nbsp;createAJavaProject(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;String&amp;nbsp;name)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;CoreException&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IWorkspaceRoot&amp;nbsp;root&amp;nbsp;=&amp;nbsp;ResourcesPlugin.getWorkspace().getRoot();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IProject&amp;nbsp;project&amp;nbsp;=&amp;nbsp;root.getProject(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;project.create(NULL_PROGRESS_MONITOR);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;project.open(NULL_PROGRESS_MONITOR);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock.addJavaNature(project,&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;SubProgressMonitor(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NULL_PROGRESS_MONITOR,&amp;nbsp;1));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IJavaProject&amp;nbsp;javaProject&amp;nbsp;=&amp;nbsp;JavaCore.create(project);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;List&amp;lt;IClasspathEntry&amp;gt;&amp;nbsp;entries&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;ArrayList&amp;lt;IClasspathEntry&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;final&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IClasspathEntry&amp;nbsp;entry&amp;nbsp;:&amp;nbsp;javaProject.getRawClasspath())&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;(entry.getEntryKind()&amp;nbsp;==&amp;nbsp;IClasspathEntry.CPE_SOURCE)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;((org.eclipse.jdt.internal.core.ClasspathEntry)&amp;nbsp;entry).path&amp;nbsp;=&amp;nbsp;Path.fromPortableString(SOURCE_FOLDER);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;entries.add(entry);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;entries.add(JavaRuntime.getDefaultJREContainerEntry());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;javaProject.setRawClasspath(entries.toArray(&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;IClasspathEntry[entries.size()]),&amp;nbsp;NULL_PROGRESS_MONITOR);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #7f0055;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;project;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;The Feature&lt;/h2&gt;
&lt;p&gt;Now that we have a tested plug-in, we will create an Eclipse feature to contain it for distribution. We can do practically all our configuration through the New Feature Project Wizard, except we want to put the feature project into a &lt;em&gt;features&lt;/em&gt; subdirectory in the same way that we put our plug-in and fragment into the &lt;em&gt;plugins&lt;/em&gt; subdirectory.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm7.static.flickr.com/6094/6236573969_93fca00579_z.jpg" alt="The New Feature Project wizard" /&gt;&lt;/p&gt;
&lt;h2&gt;The Update Site&lt;/h2&gt;
Now that we have a tested plug-in and a feature to contain it, we will create an Eclipse update site for publishing the feature. In the New Update Site Project Wizard, we will again override the default location so that our update site project is in an &lt;em&gt;update-site&lt;/em&gt; subdirectory, just as we separated our plug-in, fragment and feature into &lt;em&gt;plugins&lt;/em&gt; and &lt;em&gt;features&lt;/em&gt; subdirectories.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm7.static.flickr.com/6052/6255218901_1fd2035ca1_z.jpg" alt="The New Update Site Project wizard" /&gt;&lt;br /&gt;&lt;strong&gt;NB:&lt;/strong&gt; Whereas we may have multiple features or plug-ins for our project, we will have a single update site; thus the update-site project is not contained in a subfolder of &lt;em&gt;update-site&lt;/em&gt;, but in this folder directly. &lt;br /&gt;
&lt;h2&gt;Tycho&lt;/h2&gt;
Compiling, running integration tests and packaging an application entirely within an IDE does not scale to even a single programmer over time, let alone a team of programmers working on multiple plug-in projects. So far, the amount of ceremony for creating our menu contribution has been high, but the IDE has reduced a significant amount of the boilerplate. Before Tycho, the amount of ceremony and hackery required to get plugins, features and update sites packaged and unit and integration test suites running on a CI server had been prohibitively high. Tycho removes a significant amount of that pain. Generating meaningful poms for our projects is as trivial as going into each of the &lt;em&gt;features&lt;/em&gt;, &lt;em&gt;plugins&lt;/em&gt; and &lt;em&gt;update-site&lt;/em&gt; directories and running a Tycho goal.&lt;br /&gt;&lt;br /&gt;
&lt;div style="overflow: auto; width: 80%; padding: 5px; color: white; background-color: black; border-style: dashed; border-width: 1px;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;mvn org.eclipse.tycho:tycho-pomgenerator-plugin:generate-poms -DgroupId=timezra.eclipse&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;We can combine some of the boilerplate in each of the subproject poms in an &amp;uuml;ber-parent pom at the root of our workspace. We will also add the &lt;a href="http://www.eclipse.org/indigo/" rel="nofollow" title="Indigo" target="_blank"&gt;Indigo&lt;/a&gt; p2 repository and a &lt;a href="http://tycho.sonatype.org/targetplatformmanagement.html" rel="nofollow" title="target platform configuration resolver" target="_blank"&gt;target platform configuration resolver&lt;/a&gt; since we are developing our Eclipse components Manifest-first.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;pom.xml&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #008080;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;xml&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;version&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"1.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;encoding&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"UTF-8"&lt;/span&gt;&lt;span style="color: #008080;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xsi:schemaLocation&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://maven.apache.org/POM/4.0.0&amp;nbsp;http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xmlns&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xmlns:xsi&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modelVersion&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;4.0.0&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modelVersion&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;timezra.eclipse&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;apply-save-actions-parent&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;packaging&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;pom&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;packaging&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;properties&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;tycho-version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;0.13.0&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;tycho-version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;properties&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modules&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;plugins&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;features&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;update-site&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;module&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modules&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.eclipse.tycho&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;tycho-maven-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;${tycho-version}&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;extensions&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;extensions&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.eclipse.tycho&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;target-platform-configuration&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;${tycho-version}&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;resolver&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;p2&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;resolver&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;repositories&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;repository&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;indigo&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;layout&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;p2&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;layout&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;url&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;http://download.eclipse.org/releases/indigo/&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;url&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;repository&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;repositories&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;We will also &lt;a href="http://git.eclipse.org/c/tycho/org.eclipse.tycho.git/tree/tycho-demo/itp01/tycho.demo.itp01.tests/pom.xml" rel="nofollow" title="configure Tycho to use the UI test runner" target="_blank"&gt;configure Tycho to use the UI test runner&lt;/a&gt; for our integration test suite, as well as add any platform-specific runtime plug-in dependencies or configuration to the test fragment pom.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;plugins/timezra.eclipse.apply_save_actions.tests/pom.xml&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #008080;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;xml&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;version&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"1.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;encoding&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"UTF-8"&lt;/span&gt;&lt;span style="color: #008080;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xsi:schemaLocation&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://maven.apache.org/POM/4.0.0&amp;nbsp;http://maven.apache.org/xsd/maven-4.0.0.xsd"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xmlns&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://maven.apache.org/POM/4.0.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;xmlns:xsi&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modelVersion&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;4.0.0&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;modelVersion&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;parent&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;timezra.eclipse&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;apply-save-actions-plugins-parent&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;parent&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;timezra.eclipse&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;timezra.eclipse.apply_save_actions.tests&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;1.0.0-SNAPSHOT&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;packaging&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;eclipse-test-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;packaging&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #3f5fbf;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color: #3f5fbf;"&gt;&amp;nbsp;Tell&amp;nbsp;tycho&amp;nbsp;to&amp;nbsp;run&amp;nbsp;PDE&amp;nbsp;tests&amp;nbsp;http://git.eclipse.org/c/tycho/org.eclipse.tycho.git/tree/tycho-demo/itp01/tycho.demo.itp01.tests/pom.xml&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f5fbf;"&gt;--&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;outputDirectory&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;target/test-classes&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;outputDirectory&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.eclipse.tycho&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;tycho-surefire-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;${tycho-version}&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;useUIHarness&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;true&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;useUIHarness&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;osx&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;activation&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;property&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;name&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;java.vendor.url&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;name&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;value&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;http://www.apple.com/&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;value&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;property&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;activation&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;pluginManagement&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.eclipse.tycho&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;tycho-surefire-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;${tycho-version}&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;argLine&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;-XstartOnFirstThread&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;argLine&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;dependencies&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;dependency&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;type&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;p2-installable-unit&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;type&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.eclipse.jdt.launching.macosx&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;dependency&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;dependencies&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;configuration&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;pluginManagement&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;strong&gt;NB:&lt;/strong&gt; we would use &lt;a href="http://timezra.blogspot.com/2010/05/tycho-tests-without-osgi.html" rel="nofollow" title="a different configuration" target="_blank"&gt;a different configuration&lt;/a&gt; if our fragment contained unit-tests instead of integration tests.&lt;br /&gt;
&lt;h2&gt;JAR signing&lt;/h2&gt;
If you do not have access to a certificate from a trusted authority, you can generate a self-signed certificate with 1-year validity by a command such as&lt;br /&gt;&lt;br /&gt;
&lt;div style="overflow: auto; width: 80%; padding: 5px; color: white; background-color: black; border-style: dashed; border-width: 1px;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;keytool -genkey -alias _keystore_alias_ -keystore /path/to/keystore -validity 365&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;In order to sign the jars deployed to our update-site before release, we will add a new profile with a &lt;a href="http://www.zeroturnaround.com/blog/building-eclipse-plug-ins-with-maven-3-and-tycho/" rel="nofollow" title="plug-in management configuration" target="_blank"&gt;plug-in management configuration&lt;/a&gt; to the &amp;uuml;ber-parent pom.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;pom.xml&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #008080;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;xml&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;version&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"1.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;encoding&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"UTF-8"&lt;/span&gt;&lt;span style="color: #008080;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&amp;nbsp;....&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;....&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;sign&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #3f5fbf;"&gt;&amp;lt;!--&lt;/span&gt;&lt;span style="color: #3f5fbf;"&gt;&amp;nbsp;To&amp;nbsp;sign&amp;nbsp;plug-ins&amp;nbsp;and&amp;nbsp;features,&amp;nbsp;run:&amp;nbsp;mvn&amp;nbsp;-Psign&amp;nbsp;-Djarsigner.keystore=&amp;lt;path&amp;gt;&amp;nbsp;-Djarsigner.storepass=*******&amp;nbsp;-Djarsigner.alias=&amp;lt;keyalias&amp;gt;&amp;nbsp;clean&amp;nbsp;package&amp;nbsp;integration-test&amp;nbsp;&lt;/span&gt;&lt;span style="color: #3f5fbf;"&gt;--&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;pluginManagement&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;maven-jarsigner-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;1.2&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;version&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;executions&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;execution&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goals&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;sign&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goal&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;sign&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goal&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goals&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;execution&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;execution&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goals&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;verify&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goal&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;verify&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goal&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;goals&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;execution&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;executions&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;pluginManagement&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;....&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;Similarly, we will &lt;a href="http://www.zeroturnaround.com/blog/building-eclipse-plug-ins-with-maven-3-and-tycho/"&gt;configure the plug-ins and features parent poms for jar signing&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;plugins/pom.xml&lt;/em&gt; and &lt;em&gt;features/pom.xml&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #008080;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;xml&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;version&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"1.0"&lt;/span&gt;&amp;nbsp;&lt;span style="color: #7f007f;"&gt;encoding&lt;/span&gt;=&lt;span style="font-style: italic; color: #2a00ff;"&gt;"UTF-8"&lt;/span&gt;&lt;span style="color: #008080;"&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&amp;nbsp;....&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;....&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;sign&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;id&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;groupId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;maven-jarsigner-plugin&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;artifactId&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugin&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;plugins&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;build&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profile&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;profiles&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #008080;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #3f7f7f;"&gt;project&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;Publishing&lt;/h2&gt;
&lt;p&gt;We are now ready to build and test our signed plug-ins and features and to package them in an update site for deployment.&lt;/p&gt;
&lt;div style="overflow: auto; width: 80%; padding: 5px; color: white; background-color: black; border-style: dashed; border-width: 1px;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;mvn -Psign -Djarsigner.keystore=http://www.solutionsiq.com/path/to/keystore -Djarsigner.storepass=_keystore_password_ -Djarsigner.alias=_keystore_alias_ clean package integration-test&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;There will now be a fully deployable update site in &lt;em&gt;update-site/target/site&lt;/em&gt;.&lt;br /&gt;For this particular project, I distribute the contents of this directory to the &lt;a href="http://pages.github.com/" rel="nofollow" title="gh-pages branch" target="_blank"&gt;gh-pages branch&lt;/a&gt; of the &lt;a href="https://github.com/timezra/save-actions-extensions" rel="nofollow" title="project" target="_blank"&gt;project&lt;/a&gt; on github.&lt;br /&gt;Since the &lt;a href="http://timezra.github.com/save-actions-extensions/" rel="nofollow" title="update site for the project" target="_blank"&gt;update site for the project&lt;/a&gt; is publicly-available and since I have an &lt;a href="https://bugs.eclipse.org/bugs/" rel="nofollow" title="Eclipse Bugzilla login" target="_blank"&gt;Eclipse Bugzilla login&lt;/a&gt;, I can simply &lt;a href="http://marketplace.eclipse.org/addcontent" rel="nofollow" title="add a new solution listing" target="_blank"&gt;add a new solution listing&lt;/a&gt; to the &lt;a href="http://marketplace.eclipse.org/" rel="nofollow" title="Eclipse Marketplace" target="_blank"&gt;Eclipse Marketplace&lt;/a&gt; to make the menu contribution even more discoverable by and accessible to Eclipse users.&lt;br /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
This tutorial has provided the outline for the workflow of taking an idea for a single-featured Eclipse contribution from inception to delivery in a very short amount of time. While Eclipse tooling has for years provided the means to perform the tasks of plug-in, fragment, feature and update site publishing entirely within the IDE, it is the Tycho project that lowers the barrier to entry for scaling out plug-in development by making the build and test process far simpler to automate and to configure than other PDE-based build systems. Along the way, we have explored JAR signing and uploading of content to github and to the Eclipse Marketplace, and we have hopefully developed a menu contribution that others will find useful in their own projects.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm7.static.flickr.com/6060/6237098352_04757e5682_z.jpg" alt="The source submenu contribution for applying save actions in batch mode" /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/75478/Developing-Eclipse-Plug-ins-Program-to-Publish&lt;/span&gt;</description><pubDate>Thu, 08 Dec 2011 13:00:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:75478</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/75047/Agile-Coaching-A-Kanban-Exercise#Comments</comments><slash:comments>1</slash:comments><title>Agile Coaching: A Kanban Exercise</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/75047/Agile-Coaching-A-Kanban-Exercise</link><description>&lt;p&gt;by Dhaval Panchal&lt;/p&gt;
&lt;p&gt;Kanban at its essence is a signaling device that instructs the moving or creating in a &amp;ldquo;pull&amp;rdquo; based system. Kanban when applied within a system enables synchronization between the rhythm of demand (customer) and rhythm of production (producer). The pace or beat, of customer demand is takt time. In other words to enable just in time production of goods it is best for producers to produce goods at the same rate as the customer demands. A faster rate of production results in finished goods waiting to be consumed (inventory) and a slower rate of production results in missed opportunity costs or dissatisfied customers. This aspect of continuously tuning the producer&amp;rsquo;s rate of production to customers demand requires a continuous improvement (kaizen) mindset. &lt;a href="http://www.infoq.com/articles/hiranabe-lean-agile-kanban" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://www.infoq.com']);" rel="nofollow" title="My favorite article on Kanban" target="_blank"&gt;My favorite article on Kanban&lt;/a&gt; applied to software development is by Kenji Hiranabe. Please read that article before you dive into the details of setting up and facilitating this exercise.&lt;/p&gt;
&lt;h3&gt;Time:&lt;/h3&gt;
&lt;p&gt;60 &amp;ndash; 90 minutes&lt;/p&gt;
&lt;h3&gt;Input:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;20 Coins (any denomination)&lt;/li&gt;
&lt;li&gt;3x5 Index cards &amp;ndash; 100 pieces&lt;/li&gt;
&lt;li&gt;Table length to accomodate 4 to 5 people, preferably a U-shaped table&lt;/li&gt;
&lt;li&gt;3 Stopwatches&lt;/li&gt;
&lt;li&gt;Color paper &amp;ndash; legal size, two different colors (say Purple &amp;amp; Brown) &amp;ndash; 10 sheets for each color&lt;/li&gt;
&lt;li&gt;Facilitator&lt;/li&gt;
&lt;li&gt;3 timekeepers&lt;/li&gt;
&lt;li&gt;Flip chart or whiteboard&lt;/li&gt;
&lt;li&gt;Whiteboard markers&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Setup:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Create a table as shown below on flip chart or whiteboard&lt;/li&gt;
&lt;/ul&gt;
&lt;table style="width: 300px;" border="2" cellspacing="0" cellpadding="0" align="center"&gt;&lt;!--StartFragment--&gt; &lt;colgroup&gt; &lt;col span="4" width="75" /&gt; &lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="75" height="13"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="75"&gt;Round 1&lt;/td&gt;
&lt;td width="75"&gt;Round 2&lt;/td&gt;
&lt;td width="75"&gt;Round 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height="13"&gt;1st Coin&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height="13"&gt;1st Card&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height="13"&gt;All Coins&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td height="13"&gt;All Cards&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;There are two processing flows that are happening in opposite directions. One for the cards and another for the coins&lt;/li&gt;
&lt;li&gt;Processing steps for cards&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-1.jpg " target="_self"&gt;&lt;img id="img-1322594546935" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-1.jpg" border="0" alt="agile coaching kanban exercise 1" width="300" height="156" class="alignCenter" style="display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;Steps to process a card are intentionally complicated and one can invent any scheme do-able in a short time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Processing steps for coins is rather simple, however dependent on chance. At step n-1, the instruction is to flip a coin until it turns to &amp;lsquo;heads&amp;rsquo;. In step, participants flip all coins until the coin turns to &amp;lsquo;tails&amp;rsquo;. Repeat this loop until the last person in chain is done.&lt;/li&gt;
&lt;li&gt;For each round, you need less than 20 coins and the same number of blank index cards&lt;/li&gt;
&lt;li&gt;Setup and people arrangement (click images to view larger versions):&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-7.jpg " target="_self"&gt;&lt;img id="img-1322595713563" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-7.jpg" border="0" alt="agile coaching kanban exercise 7" width="299" height="228" class="alignCenter" style="height: 228px; width: 300px; display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The motivation behind creating opposite flows is to amplify the bottleneck effect and demonstrate the viability of the Kanban signaling mechanism in intersecting workflows, the same as in reality where people have to switch context and work on a different stream.&lt;/p&gt;
&lt;h2&gt;Exercise Context:&lt;/h2&gt;
&lt;p&gt;I set up the context for this exercise by making myself (facilitator) the owner/CEO of this operation. My company produces a magic set which requires a mathematically valid index card setup (see card processing steps) and a coin that has been flipped appropriately. The magic product set must have one card and one coin that make it possible for customers to do magic tricks. (All made up &lt;img src="http://www.dhavalpanchal.com/wp-includes/images/smilies/icon_razz.gif" alt=":P" class="wp-smiley" /&gt; )&lt;/p&gt;
&lt;p&gt;There are five team members who are producing the magic set of card + coin and three timekeepers to record production time - one for recoding 1st coin processing time and last coin processing time, second for 1st card processing time and last card processing time, and third for backup and tabulating results during each round.&lt;/p&gt;
&lt;h2&gt;Round 1&lt;/h2&gt;
&lt;p&gt;In this round, &lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;all coins must be flipped&lt;/strong&gt;&lt;/span&gt; to &amp;lsquo;heads&amp;rsquo; by a person on one end of the table before (s)he can pass the entire set of 20 coins to the next person. On the other end of the table, the person who is starting to process cards&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt; must process all cards by executing only step 1&lt;/strong&gt;&lt;/span&gt; (demarcate quadrants) before all cards are passed onto next person for step 2.&lt;/p&gt;
&lt;p&gt;Soon enough a situation similar to the one below will arise:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-3.jpg " target="_self"&gt;&lt;img id="img-1322596179966" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-3.jpg" border="0" alt="agile coaching kanban exercise" width="300" height="275" class="alignCenter" style="height: 275px; width: 300px; display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This causes a sever bottleneck mid-stream through the round and lot of wait periods for people when it happens.&lt;/p&gt;
&lt;p&gt;Timekeepers tabulate the time taken for 1st coin that completes the flow, the 1st card that completes the flow, the last coin that completes the flow, and the last card that completes the flow.&lt;/p&gt;
&lt;h2&gt;&lt;span style="font-size: 26px; line-height: 28px;"&gt;Round 2&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;After Round 1, remove the constraint of processing all coins and all cards by a person before they can be passed on the next person in processing chain. A short debrief and retrospective on Round 1 participants will show that they naturally gravitate to select small batch size, in this case the participants chose to pass a coin and card as soon as it was processed by a person.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;This is enabling reduced batch size in a PUSH based system since the participants move their processed item to next step as soon as they are done. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-4.jpg " target="_self"&gt;&lt;img id="img-1322596390588" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-4.jpg" border="0" alt="agile coaching kanban exercise 4" width="300" height="217" class="alignCenter" style="display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In Round 2, the problem of &amp;lsquo;waiting&amp;rsquo; is resolved by reducing batch size, however pushing artifacts to next step causes unpredictable bottlenecks to pop up throughout the process. Don&amp;rsquo;t be surprised if this round feels chaotic with participants egging each other on to complete their steps.&lt;/p&gt;
&lt;p&gt;As timekeepers tabulate time taken, it is clear that Round 2 processed the 1st coin and 1st card faster than round 1.&lt;strong&gt; Improved time to market!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But as an owner/producer, you know that just being first to market is not good enough - you have to continuously supply the market with your product so that you can keep the market advantage gained by faster time to market. (For those fixing production issues using the Kanban system, simply fixing the first production issue really quickly and demonstrating no predictable rhythm thereafter does not help your customers.)&lt;/p&gt;
&lt;p&gt;The stage is now set for Round 3.&lt;/p&gt;
&lt;h2&gt;Round 3&lt;/h2&gt;
&lt;p&gt;As a facilitator/owner in this context, there is some new setup steps required prior to executing Round 3.&lt;/p&gt;
&lt;h3&gt;Setup and Rules:&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-5.jpg " target="_self"&gt;&lt;img id="img-1322596535229" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-5.jpg" border="0" alt="agile coaching kanban exercise 5" width="300" height="287" class="alignCenter" style="height: 287px; width: 300px; display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each person has two different colored papers next to them, except for the first and last person since they only need one (see diagram above). Each color is marked either for card or for coin. A work in progress (WIP) limit is enforced by ensuring that only one coin or only one card can be placed in on their respective color paper. Only when a participant PULLS an item from the board can the downstream person work to fill the empty color space.&lt;/p&gt;
&lt;h3&gt;Execution:&lt;/h3&gt;
&lt;p&gt;As this round begins, the following dynamic emerges:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-6.jpg " target="_self"&gt;&lt;img id="img-1322596932423" src="http://www.solutionsiq.com/Portals/93486/images/agile-coaching-kanban-exercise-6.jpg" border="0" alt="agile coaching kanban exercise 6" width="299" height="297" class="alignCenter" style="height: 297px; width: 300px; display: block; margin-left: auto; margin-right: auto;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Reduced batch size eliminates wasteful wait periods as in Round 2. Establishing Kanban cards to enable PULL based system normalizes flow, preventing bottlenecks from building up. In the exercises that I have facilitated, the time for the 1st coin and 1st card processed are extremely close (almost within seconds) and the total time to process all cards and all coins is also very close (again almost within seconds).&lt;/p&gt;
&lt;p&gt;I was fortunate to have a video recording for one of these exercises. Following is a &lt;em&gt;selected&lt;/em&gt; transcript from the debrief. (Full transcript is 5 pages long and peoples name have been replaced by random one letters, except my name is in full.)&lt;/p&gt;
&lt;h2&gt;Debrief&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Y:&lt;/strong&gt; We were producing cards and coins at the same pace, evenly in 3rd round. we got the production flow of cards and coins..&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Z:&lt;/strong&gt; We were making money sooner and continually having product available, so we got product sooner, a more consistent delivery..&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;X: &lt;/strong&gt;Versus a lot of overhead of constantly keep stuff on shelf. This avoids the problem that we gave you a big batch in January but we can&amp;rsquo;t get anything for you until march&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;hellip;&amp;hellip;.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dhaval:&lt;/strong&gt; You said something about predictability almost 3 times, what did you mean by that?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;X:&lt;/strong&gt; Inventory was predictable, it was consistent, we had a process that was going and even though one of them was a random process you still ended up with a consistent output, because the batching system. The Kanban system allowed you to control flow and really no one was idle. Work was evenly distributed&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dhaval:&lt;/strong&gt; So, ummm.. I liked what you said. This (flips a coin) is sort of 50% chance, it is not wildly unpredictable as some software stuff could get. And you are saying that we could control something even without knowing how much flips you are going to need.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;X:&lt;/strong&gt; Yup!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A:&lt;/strong&gt; Not everybody is overloaded, you have only two buckets to watch for; it's not like there are hundreds. It isn&amp;rsquo;t that you don&amp;rsquo;t have work at sometimes and you are overloaded at other times.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&amp;hellip;&amp;hellip;&amp;hellip;.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Y:&lt;/strong&gt; In Round 3, if there is a bottleneck, if somebody is not processing well then this .. this .. signal cascades down the line and makes it apparant, right? (looks around for acknowledgement and gets some) as opposed to let&amp;rsquo;s say, if I&amp;rsquo;m the bottleneck and &lt;strong&gt;J&lt;/strong&gt; is tossing over and cards are queuing up it does not become apparent down the production line.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dhaval:&lt;/strong&gt; very interesting, so if I restate what you said was in Round 2 the output would have been a stack of queue in front of &lt;strong&gt;R&lt;/strong&gt; but in Round 3 you (1st guy to process cards) could feel the effect of &lt;strong&gt;R&lt;/strong&gt; not being able to process. All this with out having &lt;strong&gt;R&lt;/strong&gt; to explicitly communicate that I&amp;rsquo;m blocked!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;all:&lt;/strong&gt; Yeah! Yeah!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Y:&lt;/strong&gt; We could feel the flow, we were all interconnected. Builds cohesion and in the same vein build that dependency between us too.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;There are two things very sacred about using Kanban:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Limit Work in progress: WIP could be 1 item or 2 items or at most 5-7 items but definitely not 100.&lt;/li&gt;
&lt;li&gt;Have a signaling system that implicitly communicates upstream bottlenecks downstream. Never exceed your WIP limit even if this means that you have to idle (wait) for upstream process steps to free up their kanban bucket.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most Kanban implementations either blatantly disregard their WIP limit or invent new workflows for exception handling which soon becomes the norm. Instead it would serve the organization better to plain and simply idle, twiddle thumbs. Of course this would make the organization optimizers concerned for fear of underutilization. A better alternative is to utilize unused capacity to find continuous improvement experiments that will prevent similar disruption of flow in future (a &lt;a href="http://en.wikipedia.org/wiki/Kaizen" rel="nofollow" title="Kaizen" target="_blank"&gt;Kaizen&lt;/a&gt; event!)&lt;/p&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/75047/Agile-Coaching-A-Kanban-Exercise&lt;/span&gt;</description><pubDate>Wed, 30 Nov 2011 19:30:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:75047</guid></item><item><comments>http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize#Comments</comments><slash:comments>0</slash:comments><title>Programming with Groovy: Trampoline and Memoize</title><link>http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize</link><description>&lt;p&gt;by Tim Myer&lt;/p&gt;
&lt;p&gt;&lt;a href="http://groovy.codehaus.org/Download" rel="nofollow" title="Groovy 1.8" target="_blank"&gt;Groovy 1.8&lt;/a&gt; introduces two new closure functions. Memoization is the automatic caching of &lt;img id="img-1321988232215" src="http://www.solutionsiq.com/Portals/93486/images/programming-with-Groovy-trampoline-memoize.png" border="0" alt="programming with Groovy trampoline memoize" width="100" height="49" class="alignRight" style="float: right;" /&gt;closure results. Trampolining permits a form of declarative tail-call optimization. This article introduces the two concepts and demonstrates how to combine them in order to create cached, tail-recursive closures.&lt;/p&gt;
&lt;h4&gt;tl;dr&lt;/h4&gt;
&lt;p&gt;The example code from this article is &lt;a href="https://github.com/timezra/groovy-trampoline-memoize-specs" rel="nofollow" title="available on github" target="_blank"&gt;available on github&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Simple Memoization&lt;/h2&gt;
&lt;p&gt;Creating a closure that caches the result of some calculation is as easy as appending &lt;em&gt;.memoize()&lt;/em&gt; or one of the alternate &lt;em&gt;memoize...(...)&lt;/em&gt; methods that allows more fine-grained control over cache sizes to a closure declaration. One benefit of memoization includes the caching of results of long-running calculations that have no side effects. Memory leaks are a potential pitfall, which is why a maximum cache size should generally be prefered.&lt;br /&gt;The specification below contains a closure with a side-effect. This side effect happens just once, despite the closure being invoked twice.&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;em&gt;SimpleMemoizationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.groovy.trampoline_memoize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;SimpleMemoizationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;int&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;identity&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;it&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.memoize()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;"each&amp;nbsp;call&amp;nbsp;should&amp;nbsp;be&amp;nbsp;cached"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;identity&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;identity&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;Recursive Memoization&lt;/h2&gt;
&lt;p&gt;Suppose we want to memoize the results of a recursive closure call. For example, we can unroll the call tree of this naive implementation of the fibonacci function.&lt;/p&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt; The call trace for the fourth fibonacci number looks like this.&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: silver; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;___________fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;4&lt;/span&gt;&lt;span style="color: #000000;"&gt;___________&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;\&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;\&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; The closure here is entered nine times but we can see that it only needs to be entered 5 times because 4 calls are repeated. If we cache the results of the fibonacci calls, the complexity of even a naive implementation such as this will increase linearly, rather than exponentially.&lt;br /&gt;&lt;br /&gt;Unfortunately, because, in Groovy 1.8, a closure cannot invoke another closure directly, memoizing this closure is not entirely straightforward. The example directly below does not work.&lt;/p&gt;
&lt;em&gt;RecursiveMemoizationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.groovy.trampoline_memoize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;RecursiveMemoizationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;int&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.memoize()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;"calls&amp;nbsp;should&amp;nbsp;be&amp;nbsp;cached"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;actual&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;10&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;actual&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;55&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;11&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;em&gt;The stack trace when a closure calls itself.&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #ff0000;"&gt;groovy.lang.MissingMethodException:&lt;/span&gt; No signature of method: org.codehaus.groovy.runtime.memoize.Memoize$MemoizeFunction.doCall() is applicable for argument types: (java.lang.Integer) values: [9]&lt;br /&gt;Possible solutions: call(), call([Ljava.lang.Object;), call(java.lang.Object), call([Ljava.lang.Object;), findAll(), equals(java.lang.Object)&lt;br /&gt;&amp;nbsp;&amp;nbsp;at timezra.groovy.trampoline_memoize.RecursiveMemoizationSpec.$spock_initializeFields_closure1(RecursiveMemoizationSpec.groovy:11)&lt;br /&gt;&amp;nbsp;&amp;nbsp;at groovy.lang.Closure.call(Closure.java:410)&lt;br /&gt;&amp;nbsp;&amp;nbsp;at groovy.lang.Closure.call(Closure.java:423)&lt;br /&gt;&amp;nbsp;&amp;nbsp;at timezra.groovy.trampoline_memoize.RecursiveMemoizationSpec.calls should be cached(RecursiveMemoizationSpec.groovy:16)&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;Since methods can invoke memoized closures, the solution is to invoke the call method on the closure.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;RecursiveMemoizationSpec.groovy&lt;/em&gt;&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;RecursiveMemoizationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib.&lt;/span&gt;&lt;span style="color: #66ccff;"&gt;call&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib.&lt;/span&gt;&lt;span style="color: #66ccff;"&gt;call&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.memoize()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;....&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;NB:&lt;/strong&gt; The un-memoized version enters the closure 177 times, but the memoized version enters just 11.&lt;/p&gt;
&lt;h2&gt;Trampoline&lt;/h2&gt;
&lt;p&gt;Declarative tail-call optimization is as simple as adding &lt;em&gt;.trampoline()&lt;/em&gt; to a closure declaration and ensuring that recursive calls to the closure invoke the trampoline method on the closure instead of the closure itself. Some problems are more clearly solved with recursive solutions, but &lt;a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug%5Fid=4726340" rel="nofollow" title="without automatic tail-call optimization in the JVM" target="_blank"&gt;without automatic tail-call optimization in the JVM&lt;/a&gt;, recursion can quickly lead to an explosion in the size of the call stack. Trampolining is one work-around for this design tradeoff &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-11.html#%_idx_684" rel="nofollow" title="(or defect)" target="_blank"&gt;(or defect)&lt;/a&gt;.&lt;/p&gt;
&lt;em&gt;A tail-recursive fibonacci closure:&lt;/em&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;By tracing the call stack, we can see its linear growth without memoization.&lt;br /&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: silver; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;4&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;|&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;In order to avoid a &lt;span style="font-weight: bold; color: #ff0000;"&gt;java.lang.StackOverflowError&lt;/span&gt; for sufficiently large inputs, the tail-recursive closure must be explicitly &lt;em&gt;trampolined&lt;/em&gt;.&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;
&lt;em&gt;TrampolineSpec.groovy&lt;/em&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.groovy.trampoline_memoize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;TrampolineSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;int&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib.trampoline&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.trampoline()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;"tail&amp;nbsp;calls&amp;nbsp;chould&amp;nbsp;be&amp;nbsp;optimized"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;actual&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;actual&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1556111435&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1001&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;In this example, the trampolined closure is called 1001 times. If a method in Java were to call itself 1001 times, the stack would be overwhelmed. By trampolining, Groovy turns this recursion into iteration.&lt;/p&gt;
&lt;h2&gt;Memoizing a Trampolined Closure&lt;/h2&gt;
&lt;p&gt;Suppose we want to cache the results of a computationally expensive tail-recursive closure with no side effects. A trampolined closure that calls itself can easily be memoized in a separate closure declaration.&lt;/p&gt;
&lt;em&gt;OneTimeTrampolineMemoizationSpec.groovy&lt;/em&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.groovy.trampoline_memoize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;OneTimeTrampolineMemoizationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;int&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib_aux&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib_aux.trampoline&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.trampoline()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib_aux.memoize()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;"top-level&amp;nbsp;trampolined&amp;nbsp;calls&amp;nbsp;should&amp;nbsp;be&amp;nbsp;cached"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1000&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1000&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1001&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1556111435&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;NB:&lt;/strong&gt; This solution caches the top-level trampolined closure, not the results of the intermediate calls.&lt;/p&gt;
&lt;h2&gt;Trampolining a Memoized Closure&lt;/h2&gt;
&lt;p&gt;Suppose we want to cache the intermediate results of a trampolined function call. For example, in our trace above, suppose we want to cache the results of &lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;4&lt;/span&gt; and &lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt; and &lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt; and &lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt; and &lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;3&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;5&lt;/span&gt;. Again, this situation is not straightforward because no closure can call a memoized closure directly, so in this case, the trampolined closure cannot call a memoized version of itself directly. Again, we can use the call function on the memoized closure.&lt;/p&gt;
&lt;em&gt;FullTrampolineMemoizationSpec.groovy&lt;/em&gt;
&lt;div style="overflow: auto; padding: 5px; background-color: white; border-style: dashed; border-width: 1px;"&gt;&lt;span style="font-family: courier new; font-size: 11pt;"&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;package&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;timezra.groovy.trampoline_memoize&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: #972c78;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;FullTrampolineMemoizationSpec&lt;/span&gt;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;extends&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;spock.lang.Specification&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;int&lt;/span&gt;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib_aux&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib.trampoline&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.memoize()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib_aux.&lt;/span&gt;&lt;span style="color: #66ccff;"&gt;call&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;n,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;a,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;b&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}.trampoline()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #2a00ff;"&gt;"all&amp;nbsp;trampolined&amp;nbsp;calls&amp;nbsp;should&amp;nbsp;be&amp;nbsp;cached"&lt;/span&gt;&lt;span style="color: #000000;"&gt;()&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;when:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1000&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-weight: bold; color: #972c78;"&gt;def&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;fib&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;500&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;315178285&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #cd3200;"&gt;1898383934&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;then:&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #66ccff;"&gt;count&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1001&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;first&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;second&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&amp;nbsp;&lt;span style="color: #cd3200;"&gt;1556111435&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Trampolining and memoization are two powerful new features in Groovy 1.8, but the combination of the two is not always straightforward. This tutorial has presented strategies for combining the two and for working around some of the limitations of their combination.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;span style="color: #999999;"&gt;View this original blog post here: http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize&lt;/span&gt;</description><pubDate>Tue, 22 Nov 2011 19:20:00 GMT</pubDate><guid isPermaLink="false">f1397696-738c-4295-afcd-943feb885714:72880</guid></item></channel></rss>

