<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Atlassian Developer Blog</title><link>http://blogs.atlassian.com/developer/</link><language>en</language><lastBuildDate>Wed, 18 Nov 2009 17:46:58 PST</lastBuildDate><generator>Movable Type 4.1 http://www.sixapart.com/movabletype/</generator><description></description><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/AtlassianDeveloperBlog" type="application/rss+xml" /><feedburner:emailServiceId>AtlassianDeveloperBlog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><title>Tools for stand-ups in agile and scrum teams</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/vP8M_AhBiKQ/tools_for_stand-ups_in_agile_and_scrum_teams.html</link><category>Agile</category><category>programming tools</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Benjamin Naftzger</dc:creator><pubDate>Wed, 18 Nov 2009 17:46:58 PST</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5437</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><a href="http://www.atlassian.com/agile"><img src="http://blogs.atlassian.com/news/agile_development_blog_badge-thumb-185x99.png" align="right" class="noborder" alt="Agile software development at Atlassian" style="float: right; margin: 0 0 20px 20px;"></a></p>

<p>If you are using <a href="http://www.atlassian.com/agile/">scrum and agile</a> within your organization, you already know about the <a href="http://blogs.atlassian.com/developer/2009/06/getting_started_with_agile_daily_standup_meetings.html">daily stand-up meeting</a> and the value its brings to the team. Many organisations who have not fully adopted scrum still find the <a href="http://docs.google.com/gview?a=v&q=cache:8WVydGizwF8J:www.gazelles.com/columns/Daily_Meeting.pdf+verne+harnish+Daily+Meetings&hl=en&gl=us&pid=bl&srcid=ADGEEShKVNnQjU7Oxw3HtMlxaa2JES21-martABFAPYTOaE151NW06UXoDRDqm5Epi-zW0uAJRmMdQ1chc7fnDQM_en6a2LrMPy4Cz8muNZdoJfMI-9eebY5ozjH2IJSLLAW_SVFYM3u&sig=AFQjCNGdzHd-HJ9OTasxeDuq1xf4Djhbrw">stand-up meeting</a> to be extremely useful when done properly. </p>

<p>Pyxis Technologies have just released a really neat iPhone/iPod Touch app - the <a href="http://agilely.pyxis-tech.com/">_agilely Timer</a>. The application  allows you to efficiently facilitate daily stand ups, roundtable discussions and manage simple timeboxes. It costs $1.99 with all monies raised going to <a href="http://www.fian.org">FIAN - FoodFirst Information and Action Network</a>.<br />
As <a href="http://www.linkedin.com/ppl/webprofile?vmi=&id=2690904&pvs=pp&authToken=3Qsp&authType=name&locale=en_US&trk=ppro_viewmore&lnk=vw_pprofile">Francois Beauregard</a> said to me, "start standing-up for something important". </p>

<p>You can <a href="http://agilely.pyxis-tech.com/">learn more</a> about the _agilely Timer or even <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=333212198&mt=8">buy it direct from the App Store</a>.</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://agilely.pyxis-tech.com/"><img src="http://blogs.atlassian.com/developer/standup-thumb-600x488.png" width="600" height="488" alt="standup.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=vP8M_AhBiKQ:uLKR-VePJG4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=vP8M_AhBiKQ:uLKR-VePJG4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=vP8M_AhBiKQ:uLKR-VePJG4:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/vP8M_AhBiKQ" height="1" width="1"/>]]></content:encoded><description>Pyxis Technologies have just released a really neat iPhone/iPod Touch app - the _agilely Timer.</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/11/tools_for_stand-ups_in_agile_and_scrum_teams.html</feedburner:origLink></item><item><title>Code Review in Agile Teams - part I</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/m9ia7bBNcs8/code_review_in_agile_teams_part_i.html</link><category>Agile</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Wojciech Seliga</dc:creator><pubDate>Mon, 16 Nov 2009 16:25:10 PST</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5428</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="agile-manifesto-the-answer-small.png" src="http://blogs.atlassian.com/developer/2009/11/16/the-answer-small.png" width="300" height="187" class="mt-image-left" style="float: left; margin: 0 20px 20px 0;" /></span>At Atlassian we <a href="http://www.atlassian.com/agile/">believe in "agile" development</a> (similarity to a very popular buzzword recently unintended). We strive to be as agile as possible and clearly see the benefits.</p>

<p>Sure, there are teams who are "more agile", there are teams who are less. Almost every team applies different agile practices. That's OK as we believe in self-organisation and bottom-up evolution. Still we all believe in the <a href="http://agilemanifesto.org/">4 fundamental principles</a> of agile philosophy, which are compatible with <a href="http://www.atlassian.com/32/why-join.jsp#values">our company values</a>.</p>

<p>When <a href="http://www.atlassian.com/software/crucible">Crucible</a> became part of the Atlassian suite, a lot of us wondered how code review would match our agile environment.  Two years later, code review has become an integral part of our agile developers' day-to-day jobs. Some say they are addicted to it. Let me tell you why.</p>

<p>I am not going to elaborate on an obvious advantage of code review: improved code quality.  Instead, I would say that code quality is a nice <em>side effect</em>, but not the purpose of code review in our teams.</p>

<p>Code review is one tangible way that we enact the first principle of the Agile Manifesto: "Individuals and interactions over processes and tools".  Here are some examples of how code review helps us collaborate better:</p>

<h2>New team members</h2>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="tutor-child-small.jpg" src="http://blogs.atlassian.com/developer/2009/11/16/tutor-child-small.jpg" width="300" height="451" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></span>Atlassian is constantly <a href="http://www.atlassian.com/32/">growing</a>.  We hire passionate, often quite- experienced developers who need to dive into our non-trivial code base very quickly. In addition to new hires, existing team members sometimes rotate to different temporary or permanent positions.</p>

<p>Code review makes ramping up on a new code base faster and less painful, and helps maintain engineering knowledge across the team and the company over time.  People more experienced in the code base review newbies' commits (there's no better way to learn the product than to start coding bugs or stories), and then advise them on which design inconsistencies they introduced and which shared components or utilities they should use and how. In return, the newbies can bring invaluable experience, good engineering practices, useful libraries, nice patterns, tricks, etc. from their former teams, resulting in fresh insights to improve the code base.  In short, code review is a two-way conversation. Both the author and reviewers communicate and learn from each other.</p>

<p>Code review is even more important when a really junior developer joins a team.  Senior developer don't have time to hand-hold the junior folks, since they need to be coding.  That said, doing small but frequent code reviews of the junior developer's code is no big deal.  The result?  Senior developers can focus on writing code for most of the day and spend a 10-15 minutes a couple times per day to review the code changes by junior developers.  The junior developers benefit from feedback, and the senior developers haven't lost valuable coding time.</p>

<h2>Geographical distribution</h2>

<p>Atlassian develops software on 3 continents, in time zones which differ by as much as 10 hours. Most teams working on a given code base are co-located (it really helps), but sometimes it's just not practical or feasible. Thus we ended up with a few geographically distributed teams - a big problem for some agile practices such as pair programming and daily stand ups.</p>

<p>Tools-supported code review comes to the rescue here by encouraging and facilitating knowledge flow between different locations.</p>

<p>With asynchronous code reviews, time zone differences can actually be an <em>advantage</em>.  We often raise a review in the afternoon (as a good summary of our day's work), ask for review by colleagues across the ocean and go home.  When we arrive at work the next morning, we have their review feedback: they were working on it while we were asleep!  First thing in the day, we can answer questions and fix identified problems, and then proceed with our daily development tasks.</p>

<h2>Integration</h2>

<p>Code bases do not live in isolation. Most of Atlassian's products integrate with each other in some way or another.  </p>

<p>For example, I work on <a href="http://www.atlassian.com/software/ideconnector/">IDE Connectors</a>, which need to talk to Atlassian server products via remote APIs. These APIs are continuously evolving, often in response to the needs of the IDE Connector team.  The server product teams are mostly located in Sydney, and their work day is ending just as ours is beginning.  </p>

<p>Code review is the main way for the IDE Connector team to provide feedback about the remote APIs we rely on.  Whenever there is a change related to a remote API, I am one of the reviewers - thus I can learn what is going on on the server side, constructively criticise the evolution of the API, and ensure that my teams interests are at least heard if not fulfilled.</p>

<p>A similar situation arises when you need to program something in the product you normally don't work on. I call it "guest programming" - e.g. you need to add some missing API or plugin point or just fix a problem which is only reproducible in your environment.</p>

<p>Code review enables guest programming by increasing courage of both sides. The team which owns the product is less reluctant to let an outside person touch their code base, and the guest programmer has more courage because other folks will review his code to prevent any nasty bugs.</p>

<p>Talking about courage - some of us actually feel anxious when deprived of code review. Unit tests establish a safety net which helps you be courageous to mercilessly refactor and improve the code while avoiding nasty regressions. Similarly, code review is another safety net, which gives you this feeling that your crazy ideas will be evaluated by others before they will go to production, and that your great design, utilities or tricks have a chance to be spotted and reused in other places by other team member.  This is a real teamwork!</p>

<p>Code review may be difficult and costly to implement and sustain.  Not every team or team member wants to do pair programming, and code review meetings can be too time-consuming.  Obviously we use <a href="http://www.atlassian.com/software/crucible/">Crucible</a>, which handles the logistics of a review and lets developers concentrate on the most valuable part of code review: thinking about the code and providing feedback.</p>

<p>In the next instalment I'll share a few pieces of advice and precautions related to implementing code review in an agile team or company as a standard process.</p>

<p>In the third and last instalment I would like to compare pair programming with code review and reveal a few rules around code review that evolved at Atlassian.</p>

<p>Have an opinion or question? Drop us a comment below!</p>

<hr/>
<small>"Lesson" photo courtesy of eddidit / CC BY 2.0<br/>
"Obelisk" photo courtesy of Kevin Dooley / CC BY 2.0</small>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=m9ia7bBNcs8:xr3WWCwFB8o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=m9ia7bBNcs8:xr3WWCwFB8o:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=m9ia7bBNcs8:xr3WWCwFB8o:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/m9ia7bBNcs8" height="1" width="1"/>]]></content:encoded><description>At Atlassian we believe in "agile" development (similarity to a very popular buzzword recently unintended). We strive to be as agile as possible and clearly see the benefits. Sure, there are teams...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/11/code_review_in_agile_teams_part_i.html</feedburner:origLink></item><item><title>Great new tutorial on REST plugins</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/hhmud9B5Wlg/great_new_tutorial_on_rest_plugins.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Nolen</dc:creator><pubDate>Fri, 30 Oct 2009 22:14:35 PDT</pubDate><guid isPermaLink="false">tag:www.atlassian.com,2009:/software/jira/news//2.5386</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        Jonathan Doklovic, creator of the <a href="http://www.sysbliss.com/">JIRA Workflow Designer</a>, just published a <a href="http://blog.sysbliss.com/development-process/testing-atlassian-rest-plugins.html">great tutorial about developing and testing REST plugins</a> in Atlassian applications. If this is something you're working on, go check it out -- it might save you some time!


        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=hhmud9B5Wlg:9l2fCvwfYcw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=hhmud9B5Wlg:9l2fCvwfYcw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=hhmud9B5Wlg:9l2fCvwfYcw:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/hhmud9B5Wlg" height="1" width="1"/>]]></content:encoded><description>Jonathan Doklovic, creator of the JIRA Workflow Designer, just published a great tutorial about developing and testing REST plugins in Atlassian applications. If this is something you're working on, go check it...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/10/great_new_tutorial_on_rest_plugins.html</feedburner:origLink></item><item><title>And the winners of Codegeist IV are... </title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/tKJwDSf2HA4/and_the_winners_of_codegeist_iv_are.html</link><category>Codegeist</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jens Schumacher</dc:creator><pubDate>Tue, 17 Nov 2009 16:04:34 PST</pubDate><guid isPermaLink="false">tag:www.atlassian.com,2009:/software/jira/news//2.5371</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        We have announced the winners of our 4th annual <a href="http://www.atlassian.com/codegeist/">Codegeist competition</a> live on stage at a fantastic <a href="http://www.atlassian.com/about/events/atlascamp/">Atlascamp</a> yesterday. And now it is time to reveal the results to the rest of the world. 

<p>But before we announce the winners, let's take a quick look at what the contestants were coding for. This years competition had prizes valued at over $54,000 USD up for grabs including $5,000 in cash, a MacBook Pro, an Amazon Kindle, free conference passes and a whole bunch of software from Atlassian and our generous sponsors. 
</p>
<p>
This year, in addition to the Grand Prize, we've divided Codegeist into four categories.
</p>

<ul>
	<li>Best Cross-product Integration</li>
	<li>Best Theme</li>
	<li>Most elegant use of Javascript</li>
	<li>OpenSocial Gadget</li>
</ul>

<p>Without further ado, here are the winners:</p>

<h2>Category Winners</h2>

<h3>Best Cross-product Integration</h3>
And the prize for best cross-product integration goes to<strong> Bob Swift</strong> and his <a href="http://confluence.atlassian.com/display/CODEGEIST/Atlassian+Command+Line+Interface">Atlassian Command Line Interface</a>. His command line interface (CLI) allows for remotely accessing Atlassian products. This provides a convenient way to automate administration tasks and content for Atlassian products. 

<h3>Best Theme</h3>
The prize for the best theme goes to <strong>Lukas Karrer</strong> and <strong>Thomas Botton</strong> and their <a href="https://plugins.atlassian.com/plugin/details/13887">Confluence Intranet Theme</a>. The theme is designed for more hierarchically structured content (as found in intranets) and makes content easier accessible via a menu based navigation.

<h3>Most elegant use of Javascript</h3>
The most elegant use of Javascript was demonstrated by <strong>David Chui</strong> and his <a href="https://plugins.atlassian.com/plugin/details/14297">Confluence Page History Slider</a>. It allows users to visualise differences between historical versions of a page in full rendered view utilising a slider interface to quickly navigate between versions. 

<h3>Best OpenSocial Gadget</h3>
The best OpenSocial Gadget was submitted by <strong>Ross Rowe</strong>. His <a href="https://plugins.atlassian.com/plugin/details/13536">Sonar Gadget</a> plugin provides a set of gadgets that integrate <a href="http://sonar.codehaus.org/">Sonar</a> information within a JIRA dashboard. By incorporating one or more gadgets that display the code quality metrics within a Dashboard next to your Bamboo builds, Jira issues and other information, all the members of your team can quickly get a picture as to how your project is travelling.

<h2>The Grand Prize</h2>

<h3>2nd Prize</h3>
The 2nd Prize this year goes to <strong>Ferenc Kiss</strong> and the <a href="https://plugins.atlassian.com/plugin/details/123">Confluence Archiving Plugin</a>. This plugin helps you to keep your content fresh and relevant. It archives pages that have not been updated for a long time or have been labeled with archive. Additionally, it sends emails to the author and contributors of a page when it is about to expire. 

<h3>1st Prize</h3>

And the winner of this years Codegeist Grand Prize is... <strong>Jamie Echlin</strong> and the <a href="http://confluence.atlassian.com/display/CODEGEIST/JIRA+Behaviours+Plugin">JIRA Behaviours Plugin</a>. The behaviours plugin allows an administrator to create one more or behaviours, which can be thought of as "Behaviour Schemes". A behaviour defines how fields behave. Some examples of behaviours are:
<p>
<ul>
	<li>Making a field mandatory depending on other data entered in to the form</li>
	<li>Making a field read-only dependent on user role or group</li>
	<li>Doing server-side validation of field data, before the form is submitted</li>
	<li>Setting a field value dependent on other form data</li>
</ul>
</p>
<strong>Congratulations to all winners from all of us here at Atlassian! </strong>

<h2>Thanks</h2>
<h3>Plugin Developers</h3>
A big<strong> thank you</strong> to all contestants this year! Codegeist IV had an amazing number of great entries and we hope you had as much fun writing the plugins as we had exploring all the cool functionality you guys added to our products. You guys rock&#33;

<h3>Sponsors</h3>
Our sincere thanks to <a href="http://balsamiq.com" class="external-link" rel="nofollow">Balsamiq</a>, <a href="http://gliffy.com" class="external-link" rel="nofollow">Gliffy</a>, <a href="http://infoq.com" class="external-link" rel="nofollow">InfoQ</a>, <a href="http://www.jetbrains.com" class="external-link" rel="nofollow">JetBrains</a>, <a href="http://www.oreilly.com" class="external-link" rel="nofollow">O'Reilly</a>, <a href="http://www.sysbliss.com/software" class="external-link" rel="nofollow">Sysbliss</a>, and <a href="http://www.yourkit.com" class="external-link" rel="nofollow">YourKit</a>. 

<p>
<div style="text-align:center;"><img src="http://blogs.atlassian.com/developer//codegeist-IV-sponsors.png" alt="codegeist-IV-sponsors.png" border="0" width="600" /></div></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=tKJwDSf2HA4:X7i7VH8GKho:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=tKJwDSf2HA4:X7i7VH8GKho:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=tKJwDSf2HA4:X7i7VH8GKho:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/tKJwDSf2HA4" height="1" width="1"/>]]></content:encoded><description>We have announced the winners of our 4th annual Codegeist competition live on stage at a fantastic Atlascamp yesterday. And now it is time to reveal the results to the rest of the world. </description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/10/and_the_winners_of_codegeist_iv_are.html</feedburner:origLink></item><item><title>Automated performance testing using JMeter and Maven</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/RKPs1WkzAPA/automated_performance_testing_using_jmeter_and_maven.html</link><category>Agile</category><category>Java</category><category>Testing</category><category>programming tools</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">George Barnett</dc:creator><pubDate>Mon, 02 Nov 2009 17:39:08 PST</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5357</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><a href="http://www.atlassian.com/agile"><img src="http://blogs.atlassian.com/news/agile_development_blog_badge-thumb-185x99.png" align="right" class="noborder" alt="Agile software development at Atlassian" style="float: right; margin: 0 0 20px 20px;"></a></p>

<p>When I think of <a href="http://www.atlassian.com/agile">Agile</a>, I tend to think of the awesomeness it can bring me as a performance engineer.  I see short cycles where the code is usually always stable and features are delivered incrementally.  I get to watch the performance of the system evolve over time.  Unfortunately, this means I'm testing software <b>all the time</b>.  Thats fine though - none of this is by hand - this kind of repetitive task is perfect for automation.</p>

<p>It's clear that automating testing is important - automated tests mean you have more time to do investigation while you make your build system do the repetitive tasks, and when your build system does the heavy lifting then it's easier to test more regularly.  More regular testing means you find problems sooner and go home on time.</p>

<p>In this blog, I'm going to go over how to take your JMeter performance tests and put them into a Maven build which you can run on your continuous integration server as often as is needed.  I'll introduce you to the <a href="http://mojo.codehaus.org/chronos-maven-plugin/index.html" class="external-link" rel="nofollow">Chronos</a> Maven plugin which can control JMeter in a repeatable way and has reporting features which can be used to gain useful information about the performance test.</p>

<p><br><br />
<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blogs.atlassian.com/developer/pfe-history-response-summary-fixedloadtest.html" onclick="window.open('http://blogs.atlassian.com/developer/pfe-history-response-summary-fixedloadtest.html','popup','width=800,height=400,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blogs.atlassian.com/developer/pfe-history-response-summary-fixedloadtest-thumb-800x400.png" width="600" height="300" alt="pfe-history-response-summary-fixedloadtest.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span></p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Prerequisites%3A"></a>Prerequisites:</h3>

<p>For this blog, you'll need the following prerequisites:</p>
<ul>
	<li>A working knowledge of Maven</li>
	<li>Working JMeter Performance tests</li>
	<li>A Maven repository set up for retrieving artifacts and deploying new ones.</li>
</ul>

<p>Atlassian has a well maintained Maven infrastructure - if you're just getting started, I'd suggest you read Sherali Karimov's great guide on setting up Maven infrastructure <a href="http://blogs.atlassian.com/developer/2008/02/maven_in_our_development_proce.html" class="external-link" rel="nofollow">here</a>.</p>

<p>The JMeter tests used in this paper are fairly complete, however this is not necessary for your first pass at getting the automation running.  Its more important to get started and then improve what you have as your need more features.</p>

<p>When you are writing your JMeter tests, I would suggest keeping the information about the data you're going to be testing separate from the testing logic.  By this, I mean keep the "flow" of your test in JMeter but use CSV files to define what URLs or options need to be used when testing.  For example, instead of hardcoding a list of pages to sample rather put this into the CSV and load that into JMeter using the "CSV Dataset" controller.  This way, you can change the CSV files to test a different set of pages or data in your application.</p>

<p>Here are the main steps I'm going to cover:</p>

<ol>
	<li>Create a performance test Maven artefact
	<ol>
		<li>Write a Maven pom.xml for the performance tests</li>
		<li>Package &amp; deploy the tests to the Maven repository</li>
	</ol>
	</li>
	<li>Write a Maven pom.xml to run the performance tests against an application</li>
	<li>Run the tests</li>
	<li>Automate the tests with Bamboo</li>
</ol>

<p align="center">
<br>
<big><strong>George Barnett discusses performance testing inside Atlassian</strong></big>
<br><br><object width="640" height="391" type="application/x-shockwave-flash" name="ep_player" id="ep_player" data="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoj450xsvaq4%2Fconfig.xml&autoplay=false"><param value="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoj450xsvaq4%2Fconfig.xml&autoplay=false" name="movie"/><param value="always" name="AllowScriptAccess"/><param value="true" name="allowfullscreen"/><embed width="640" height="391" type="application/x-shockwave-flash" src="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoj450xsvaq4%2Fconfig.xml&autoplay=false" name="ep_player" mce_src="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoj450xsvaq4%2Fconfig.xml&autoplay=true" id="ep_player" allowscriptaccess="always" allowfullscreen="false"/><a mce_href="http://analytics.episodic.com/download/emoj450xsvaq4/f20/performance-engineer-on-tools-that-help.mp4" href="http://analytics.episodic.com/download/emoj450xsvaq4/f20/performance-engineer-on-tools-that-help.mp4"><img width="640" height="360" border="0" src="http://cdn.episodic.com/shows/assets/480/a7647.jpg" mce_src="http://cdn.episodic.com/shows/assets/480/a7647.jpg"/></a></object>
</p>

<p><br />
<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Createaperformancetestartefact"></a>Create a performance test artefact</h3></p>

<p>In order to use your performance tests in an automated environment, you need to get them into Maven.  Below are the components for a sample artefact, starting with the directory structure to use.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="toolbar: false; theme: default; brush: java; gutter: false">
./pom.xml
./src
./src/main
./src/main/assembly
./src/main/jmeter
./src/main/resources
</pre>
</div></div>
<p>There are 3 directories in the <b>src/main</b> tree:</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Directory </th>
<th class='confluenceTh'> Purpose </th>
</tr>
<tr>
<td class='confluenceTd'> assembly </td>
<td class='confluenceTd'> For the <b>public-distribution.xml</b> which contains information about how to package the artefact </td>
</tr>
<tr>
<td class='confluenceTd'> jmeter </td>
<td class='confluenceTd'> JMeter performance tests </td>
</tr>
<tr>
<td class='confluenceTd'> resources </td>
<td class='confluenceTd'> CSV resources files </td>
</tr>
</tbody></table>
</div>

<p>In this test artefact, the CSV resource files which are distributed should contain the bare minimum information needed to run the test - the actual data you will use will be stored in another project.  If your application has a demonstration dataset then it would be good to add information about this data to the CSV files as an example.&nbsp; Don't leave the files blank - it makes it easier for others if you have a simple structure inside as an example.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="toolbar: false; theme: default; brush: java; gutter: false">
$ cat pagePaths.csv
/path/to/page.html
</pre>
</div></div>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Writeapom.xmlfortheJMetertests"></a>Write a pom.xml for the JMeter tests</h3>

<p>Resource: <span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://blogs.atlassian.com/developer/pfe-perftest-pom.xml">pfe-perftest-pom.xml</a></span></p>

<p>To deploy this project using Maven you'll need to write the pom.xml. I've attached a sample pom.xml to this post but here's some of the things you need to take care of:</p>

<p>Parent Pom:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;parent&gt;
  &lt;groupId&gt;com.atlassian.pom&lt;/groupId&gt;
  &lt;artifactId&gt;atlassian&#45;public&#45;pom&lt;/artifactId&gt;
  &lt;version&gt;14&lt;/version&gt;
&lt;/parent&gt;
</pre>
</div></div>
<p>Atlassian's performance tests are public.  For this reason, I include the Atlassian Public pom as a parent.  This ensures that this project inherits the correct settings and will be deployed to the correct place.</p>

<p>Artifact Id and Version:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;groupId&gt;com.atlassian.performance.fisheye&lt;/groupId&gt;
&lt;artifactId&gt;performance&#45;test&lt;/artifactId&gt;
&lt;packaging&gt;pom&lt;/packaging&gt;
&lt;name&gt;FishEye Performance Tests&lt;/name&gt;
&lt;version&gt;2.0&#45;SNAPSHOT&lt;/version&gt;
</pre>
</div></div>
<p>To keep things easy, set the version of the pom to the same as whatever software you're testing. When the software you're testing releases, bump the version to follow them (don't forget to tag the previous release&#33;).</p>

<p>The <b>build</b> section of the pom.xml has two plugins:</p>

<p>Resource: <span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://blogs.atlassian.com/developer/pfe-public-distribution.xml">pfe-public-distribution.xml</a></span></p>

<ol>
	<li>Maven <a href="http://maven.apache.org/plugins/maven-assembly-plugin/" class="external-link" rel="nofollow">assembly</a> plugin. &nbsp;This uses the <b>public-distribution.xml</b> configuration file to package the tests and the sample dataset into a .zip and .tar.gz archive. &nbsp;It specifies which files and directories should be included into the generated archive.</li>
	<li>Maven <a href="http://maven.apache.org/plugins/maven-clean-plugin/" class="external-link" rel="nofollow">clean</a> plugin.  This plugin is set up to remove any <b>.jtl</b> files from the results directory to prevent leaking any test results into the archive file. <b>.jtl</b> is the extension given to output files that <b>Listeners</b> save result data in during the JMeter test run.</li>
</ol>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-PackagingtheJMetertest"></a>Packaging the JMeter test</h3>

<p>If everything is in place you should now be able to use Maven to package and deploy the JMeter tests to your Maven repository.  This is the first step to being able to include them in a repeatable test.</p>

<p>First, check that the artefact generated is correct:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="toolbar: false; theme: default; brush: java; gutter: false">
spoem:trunk gbarnett$ mvn verify
&#91;INFO&#93; Scanning for projects...
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; Building Performance Tests
&#91;INFO&#93;    task&#45;segment: &#91;verify&#93;
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; &#91;site:attach&#45;descriptor&#93;
&#91;INFO&#93; &#91;assembly:attached &#123;execution: public&#125;&#93;
&#91;INFO&#93; Reading assembly descriptor: /Users/gbarnett/fisheye/performance&#45;test/trunk/src/main/assembly/public&#45;distribution.xml
&#91;INFO&#93; Building zip: /Users/gbarnett/fisheye/performance&#45;test/trunk/target/performance&#45;test&#45;2.0&#45;SNAPSHOT.zip
&#91;INFO&#93; Building tar : /Users/gbarnett/fisheye/performance&#45;test/trunk/target/performance&#45;test&#45;2.0&#45;SNAPSHOT.tar.gz
...
</pre>
</div></div>

<p>Check the resulting ZIP files to ensure that they're packaged correctly. &nbsp;Check that all the files you need are there. &nbsp;For an example of what a working artefact looks like, have a look at the FishEye performance test artefacts <a href="http://maven.atlassian.com/public-snapshot/com/atlassian/performance/fisheye/performance-test/2.0-SNAPSHOT/" class="external-link" rel="nofollow">here</a>&nbsp;</p>

<p>Once you're happy with this, you can deploy to the remote repository.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: java; gutter: false">
spoem:trunk gbarnett$ mvn deploy
&#91;INFO&#93; Scanning for projects...
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; Building Performance Tests
&#91;INFO&#93;    task&#45;segment: &#91;deploy&#93;
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; &#91;site:attach&#45;descriptor&#93;
&#91;INFO&#93; &#91;assembly:attached &#123;execution: public&#125;&#93;
&#91;INFO&#93; Reading assembly descriptor: /Users/gbarnett/fisheye/performance&#45;test/trunk/src/main/assembly/public&#45;distribution.xml
&#91;INFO&#93; Building zip: /Users/gbarnett/fisheye/performance&#45;test/trunk/target/performance&#45;test&#45;2.0&#45;SNAPSHOT.zip
&#91;INFO&#93; Building tar : /Users/gbarnett/fisheye/performance&#45;test/trunk/target/performance&#45;test&#45;2.0&#45;SNAPSHOT.tar.gz
&#91;INFO&#93; &#91;install:install&#93;
..
&#91;INFO&#93; &#91;deploy:deploy&#93;
..
&#91;INFO&#93; Retrieving previous build number from atlassian&#45;m2&#45;snapshot&#45;repository
Uploading: &#104;ttps://maven.atlassian.com/public&#45;snapshot/com/atlassian/performance/fisheye/performance&#45;test/2.0&#45;SNAPSHOT/performance&#45;test&#45;2.0&#45;20080929.031627&#45;1.zip
&#91;INFO&#93; Retrieving previous build number from atlassian&#45;m2&#45;snapshot&#45;repository
Uploading: &#104;ttps://maven.atlassian.com/public&#45;snapshot/com/atlassian/performance/fisheye/performance&#45;test/2.0&#45;SNAPSHOT/performance&#45;test&#45;2.0&#45;20080929.031627&#45;1.tar.gz
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; BUILD SUCCESSFUL
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
&#91;INFO&#93; Total time: 41 seconds
&#91;INFO&#93; Final Memory: 14M/762M
&#91;INFO&#93; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
</pre>
</div></div>
<p>If you see this it means you have successfully deployed your JMeter tests to your Maven repository. If you find that Maven has failed then go over the setup carefully to check everything is in place.  If you require more debugging information from Maven, you can run the above commands with the <b>&#45;X</b> switch to enable more logging.</p>

<p>Once the build is successful and your artefacts are deployed to your Maven repository, they can then be included in your automated performance test.&nbsp; In the next part, I'll create project which will run the performance tests against your application. &nbsp;This Maven build can then be automated.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Directorystructurefortheautomatedtest"></a>Directory structure for the automated test</h3>

<p>The structure for the automated test is slightly different as you can see below. &nbsp;Create a new project in your SCM and create the directories listed.</p>

<p>The main difference is that we're using the <b>test</b> directory instead of <b>main</b>.  This is because the main purpose of this project is to run tests instead of build an artefact.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: java; gutter: false">
./pom.xml
./src
./src/test
./src/test/resources
./src/test/resources/jprofilerconfig.xml
./src/test/resources/dataset&#45;sanity1
./src/test/resources/dataset&#45;sanity1/config.xml
./src/test/resources/dataset&#45;sanity1/repository
./src/test/resources/dataset&#45;sanity1/repository/filePaths.csv
./src/test/resources/dataset&#45;sanity1/repository/repoNames.csv
./src/test/resources/dataset&#45;sanity1/repository/repoPaths.csv
./src/test/resources/dataset&#45;sanity1/search
./src/test/resources/dataset&#45;sanity1/search/complexTerms.csv
./src/test/resources/dataset&#45;sanity1/search/eyeqlTerms.csv
./src/test/resources/dataset&#45;sanity1/search/simpleTerms.csv
</pre>
</div></div>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Writeapom.xmlfortheautomatedtest"></a>Write a pom.xml for the automated test</h3>

<p>Resource: <span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://blogs.atlassian.com/developer/pfe-automation-pom.xml">pfe-automation-pom.xml</a></span></p>

<p>It's best to start out by working out what actions (and in which order) you will need to take to test your application.  In this example, here are the steps the test will perform:</p>

<ol>
	<li>Prepare the FishEye data directory using the chosen data to load</li>
	<li>Prepare the Jprofiler config</li>
	<li>Download and extract the FishEye application</li>
	<li>Start FishEye</li>
	<li>Run a JMeter test using the defined CSV data</li>
	<li>Stop FishEye</li>
	<li>Run reporting on the JMeter outputs and generate a site directory for upload</li>
</ol>

<p><br />
<p>It's important to define what order this work should occur in before starting so you know what you are aiming for.&nbsp; I'm not going to annotate the whole <span class="mt-enclosure mt-enclosure-file" style="display: inline;"><a href="http://blogs.atlassian.com/developer/pfe-automation-pom.xml">pom.xml</a></span> since it is several hundred lines long.&nbsp; I'll go over the important parts which you may not have seen before - I would suggest opening a copy locally before proceeding.</p></p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3ADefinebuildprofiles"></a>POM: Define build profiles</h3>

<p>There will be many tasks to perform and settings to choose when running the test.  Some of these tasks will need to happen every time (for example, setting up a database) and others will only need to happen when you are testing something specific (such as adding a code profiler).  Maven provides the concept of <a href="http://maven.apache.org/guides/introduction/introduction-to-profiles.html" class="external-link" rel="nofollow">Profiles</a> (not to be confused with code profiling) which can be used to add and remove plugins to your test harness.</p>

<p>In this example, I will set up two profiles.  By default, the information contained in them will not be used but when we do want to use it, it can be added to the test with a simple switch.</p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Profile </th>
<th class='confluenceTh'> Task </th>
</tr>
<tr>
<td class='confluenceTd'> profile </td>
<td class='confluenceTd'> Run JProfiler before starting the build to gather CPU snapshots </td>
</tr>
<tr>
<td class='confluenceTd'> dataset-sanity1 </td>
<td class='confluenceTd'> Controls the backend data to be loaded into Fisheye and the data CSVs to be passed to JMeter </td>
</tr>
</tbody></table>
</div>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3AImportDependencies"></a>POM: Import Dependencies</h3>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;dependency&gt;
  &lt;groupId&gt;com.atlassian.performance.fisheye&lt;/groupId&gt;
  &lt;artifactId&gt;performance&#45;test&lt;/artifactId&gt;
  &lt;type&gt;zip&lt;/type&gt;
  &lt;version&gt;$&#123;project.version&#125;&lt;/version&gt;
&lt;/dependency&gt;
</pre>
</div></div>
<p>The JMeter performance test artefact we packaged up earlier is a dependency in this test.  Using the <b>maven-dependency-plugin</b> this artefact will be extracted into the <b>target/test-classes/</b> directory for use.</p>

<p>The <b>maven-dependency-plugin</b> is also used to download and extract the application that's going to be tested.</p>

<p>The Maven <a href="http://mojo.codehaus.org/exec-maven-plugin/" class="external-link" rel="nofollow">exec</a> plugin is used to start FishEye using the <b>exec:exec</b> goal.  FishEye is started at the <b>pre-integration-test</b> phase so it's ready for use with the JMeter goals which run at <b>integration-test</b> phase.&nbsp; If your application runs inside an application server such as Tomcat or Jetty, you should use the Maven <a href="http://cargo.codehaus.org/Maven2+plugin" class="external-link" rel="nofollow">Cargo</a> plugin to start and stop your application.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3APluginsJMeterconfiguration"></a>POM: Plugins - JMeter configuration</h3>

<p>The JMeter test is run by the Maven <a href="http://mojo.codehaus.org/chronos-maven-plugin/index.html" class="external-link" rel="nofollow">Chronos</a> plugin which is responsible for running JMeter.  There a few settings which you need to pay attention to:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;plugin&gt;
  &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
  &lt;artifactId&gt;chronos&#45;maven&#45;plugin&lt;/artifactId&gt;
  &lt;version&gt;1.0&lt;/version&gt;
  &lt;configuration&gt;
    &lt;jmeterhome&gt;$&#123;jmeter.home&#125;&lt;/jmeterhome&gt;
    &lt;historydir&gt;$&#123;history.directory&#125;&lt;/historydir&gt;
    &lt;heap&gt;756m&lt;/heap&gt;
</pre>
</div></div>
<p><b>jmeterhome</b></p>

<p>Where JMeter is installed but the base directory - JMeter should be in bin/jmeter under this directory.  It's worth nothing that the plugin does not start jmeter via the startup script but rather invokes the jar's directly.</p>

<p><b>historydir</b></p>

<p>This variable should be a unique directory for the build.  Since you're going to eventually have several profiles with different datasets and JVM versions, it should take this into account.  I use the following format:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>history.directory / product / product.version-java.version-data.version
</pre>
</div></div>
<p><b>heap</b></p>

<p>It's important to give JMeter enough memory.  This is especially true if your test uses multiple Listeners.  As you will see later when I cover reporting, the default report will include a graph showing Garbage Collection. This graph is actually JMeters garbage collection, but it's good to keep an eye on it. If JMeter spends too much time doing GC then the test results will be skewed and useless.</p>

<p>The settings in the attached <b>pom.xml</b> include some tweaks to the Garbage Collection, new size and survivor ratio.

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3APluginsJMeterSystemProperties"></a>POM: Plugins - JMeter System Properties</h3>

<p>These variables are initially set as global configuration items but are then overridden in the profile for the dataset used.&nbsp; The variables here will be passed to JMeter using the <b>&#45;Dvariable.name=value</b> command line switch.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;sysproperties&gt;
  &lt;property&gt;
    &lt;name&gt;script.runtime&lt;/name&gt;
    &lt;value&gt;$&#123;script.fixedload.runtime&#125;&lt;/value&gt;
  &lt;/property&gt;
  &lt;property&gt;
    &lt;name&gt;script.base&lt;/name&gt;
    &lt;value&gt;$&#123;project.build.directory&#125;/performanceTest&lt;/value&gt;
  &lt;/property&gt;
  &lt;property&gt;
    &lt;name&gt;resource.dir&lt;/name&gt;
    &lt;value&gt;$&#123;dataset.location&#125;&lt;/value&gt;
  &lt;/property&gt;
&lt;/sysproperties&gt;
</pre>
</div></div>
<p>JMeter accepts external variable input using the <a href="http://jakarta.apache.org/jmeter/usermanual/functions.html#__P" class="external-link" rel="nofollow">P</a> function, eg: ${__P(<b>script.runtime</b>,1800)}</p>

<p>Using sysproperties in the pom, it's possible to override the variables inside the JMeter test.  The most useful reason for this doing is to change the location of the resources which contains the CSV files which define which pages to sample directory.  In the above example, the <b>dataset.location</b> variable is modified by the chosen profile in the pom and this is passed to JMeter, thus allowing the override of the resource directory used for testing.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3APluginsJMetertestexecutions"></a>POM: Plugins - JMeter test executions</h3>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;executions&gt;
  &lt;execution&gt;
  &lt;id&gt;71&#95;fixedload&#45;test&lt;/id&gt;
    &lt;configuration&gt;
      &lt;dataid&gt;fixedloadtest&lt;/dataid&gt;
       &lt;input&gt;$&#123;project.build.directory&#125;/performanceTest/jmeter&#45;test&#45;fixedload.jmx&lt;/input&gt;
    &lt;/configuration&gt;
    &lt;goals&gt;
      &lt;goal&gt;jmeter&lt;/goal&gt;
      &lt;goal&gt;check&lt;/goal&gt;
      &lt;goal&gt;savehistory&lt;/goal&gt;
    &lt;/goals&gt;
  &lt;/execution&gt;
&lt;/executions&gt;
</pre>
</div></div>
<p>The <b>sysproperties</b> shown earlier will be applied to all exections of the plugin.  There are however two config variables above must be unique for each execution however:</p>

<p><b>dataid</b></p>

<p>This provides a unique name the test data output will be known as.  It will be used to save files in the reports later and the savehistory goal will use this to save the data for this execution.</p>

<p><b>input</b></p>

<p>This is the <b>.jmx</b> performance test script to run.&nbsp;</p>

<p><br />
<h3><a name="AutomatedperformancetestingusingJMeterandMaven-ChronosBuildGoals"></a>Chronos Build Goals</h3></p>

<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Goal </th>
<th class='confluenceTh'> Action </th>
</tr>
<tr>
<td class='confluenceTd'> JMeter </td>
<td class='confluenceTd'> Performs the test using the <b>.jmx</b> file specified in each execution </td>
</tr>
<tr>
<td class='confluenceTd'> Check </td>
<td class='confluenceTd'> Parses the output logfile and checks the samples against a ruleset in the pom.xml (not shown) to decide whether to fail the build or not. </td>
</tr>
<tr>
<td class='confluenceTd'> Savehistory </td>
<td class='confluenceTd'> Saves the history of the build to the history directory in order to build up long term data. </td>
</tr>
</tbody></table>
</div>

<p><br />
<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3AReporting"></a>POM: Reporting</h3></p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;reporting&gt;
  &lt;plugins&gt;
    &lt;plugin&gt;
      &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
      &lt;artifactId&gt;chronos&#45;maven&#45;plugin&lt;/artifactId&gt;
      &lt;version&gt;1.0&#45;atlassian&#45;1&lt;/version&gt;
      &lt;configuration&gt;
        &lt;historydir&gt;$&#123;history.directory&#125;&lt;/historydir&gt;
      &lt;/configuration&gt;
      &lt;reportSets&gt;
        &lt;reportSet&gt;
          &lt;id&gt;fixedloadreport&lt;/id&gt;
          &lt;configuration&gt;
            &lt;dataid&gt;fixedloadtest&lt;/dataid&gt;
            &lt;reportid&gt;jmeter&#45;fixedload&#45;report&lt;/reportid&gt;
            &lt;title&gt;JMeter Fixed Load Test Report&lt;/title&gt;
            &lt;description&gt;
              &lt;&#33;&#91;CDATA&#91;Fixed Load Test Report&#93;&#93;&gt;
            &lt;/description&gt;
          &lt;/configuration&gt;
          &lt;reports&gt;
            &lt;report&gt;report&lt;/report&gt;
            &lt;report&gt;historyreport&lt;/report&gt;
          &lt;/reports&gt;
        &lt;/reportSet&gt;
      &lt;/reportSets&gt;
    &lt;/plugin&gt;
  &lt;/plugins&gt;
&lt;/reporting&gt;
</pre>
</div></div>
<p>The reporting lifecycle produces graphs, one of which I've shown as an example at the top of the page.  You should include one <b>reportSet</b> for each <b>execution</b> that was defined in the <b>build</b> part of the <a href="http://mojo.codehaus.org/chronos-maven-plugin/index.html" class="external-link" rel="nofollow">Chronos</a> plugin.  The <b>dataid</b> of the <b>reportSet</b> should match the relevant test execution <b>dataid</b>.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-POM%3AProfiles"></a>POM: Profiles</h3>

<p>In order to control the dataset, I've added a profile for each piece of data I will be loading into FishEye.  At the moment, I have only one, but making another will be easy with profiles.  Most of the profile will be setting up variables which will be used elsewhere in the pom.  For example, the <b>dataset.location</b> variable will be passed into JMeter using a <b>sysproperty</b> to set the resource base directory.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">

<pre class="toolbar: false; theme: default; brush: xml; gutter: false">
&lt;profile&gt;
  &lt;id&gt;dataset&#45;sanity1&lt;/id&gt;
  &lt;properties&gt;
    &lt;repository.zipfile&gt;$&#123;performance.datadir&#125;/sanity1.zip&lt;/repository.zipfile&gt;
    &lt;repository.location&gt;$&#123;repository.basedir&#125;/sanity1&lt;/repository.location&gt;
    &lt;dataset.location&gt;$&#123;dataset.basedir&#125;/dataset&#45;sanity1&lt;/dataset.location&gt;
    &lt;dataset.version&gt;sanity1&lt;/dataset.version&gt;
    &lt;fisheye.config&gt;$&#123;dataset.location&#125;/config.xml&lt;/fisheye.config&gt;
  &lt;/properties&gt;
&lt;/profile&gt;</pre>
</div></div>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-RuntheTests%5C%21"></a>Run the Tests&#33;</h3>

<p>Once your pom is complete, you can run the test using the <b>mvn</b> command.  Don't forget to have any profiles you need as part of the command:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre>$ mvn verify site -P dataset-sanity1
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building FishEye Performance Test Runner
[INFO]    task-segment: [clean, site]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing chronos:report
[INFO] [dependency:unpack {execution: 30_unpack-fisheye-zip}]..
[INFO] [exec:exec {execution: 60_start-fisheye}]
..
[INFO] [chronos:jmeter {execution: 71_fixedload-test}]
[INFO] Excuting test /Users/gbarnett/fisheye/automated-perftest/trunk/target/performanceTest/jmeter-test-fixedload.jmx
[INFO] Created the tree successfully using /Users/gbarnett/fisheye/automated-perftest/trunk/target/performanceTest/jmeter-test-fixedload.jmx
[INFO] Starting the test @ Fri Oct 03 12:32:53 EST 2008 (1223001173145)
[INFO] Display Summary Results During Run +   783 in 184.3s =    4.2/s Avg:    22 Min:     1 Max:  1377 Err:     0 (0.00%)
[INFO] Display Summary Results During Run +  2616 in 180.0s =   14.5/s Avg:    23 Min:     1 Max:   565 Err:     0 (0.00%)
..
[INFO] Display Summary Results During Run +   448 in  25.6s =   17.5/s Avg:    41 Min:     1 Max:   861 Err:     0 (0.00%)
[INFO] Display Summary Results During Run = 29095 in 1829.9s =   15.9/s Avg:    29 Min:     1 Max:  1377 Err:     0 (0.00%)
[INFO] Tidying up ...    @ Fri Oct 03 13:03:25 EST 2008 (1223003005682)
[INFO] ... end of run
..
[INFO] [exec:exec {execution: 85_stop-fisheye}]
[INFO] [chronos:savehistory {execution: 71_fixedload-test}]
[INFO] [chronos:check {execution: 71_fixedload-test}]
..
[INFO] Generating "jmeter-fixedload-report" report.
[INFO]   tests: 10
[INFO]   jmeter samples: 29095
[INFO]  generating charts.....
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 31 minutes 39 seconds
[INFO] Finished at: Fri Oct 03 13:04:01 EST 2008
[INFO] Final Memory: 55M/746M
[INFO] ------------------------------------------------------------------------
</pre>
</div></div>

<p>The test has now run successfully.  In the <b>target</b> directory you'll find a <b>site</b> directory which contains HTML and images to make up a build report.  This will be uploaded to the URL specified in the <b>distributionManagement</b> section of the pom.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-AutomatethetestsusingBamboo"></a>Automate the tests using Bamboo</h3>

<p><a href="http://www.atlassian.com/software/bamboo/" class="external-link" rel="nofollow">Bamboo</a> is a continuous integration server made by Atlassian and is perfect for running the tests regularly.</p>

<p>For information on creating a new build plan in Bamboo, see the document <a href="http://confluence.atlassian.com/display/BAMBOO/Creating+a+Plan" class="external-link" rel="nofollow">Creating a build plan</a> in the online documentation for Bamboo.</p>

<h3><a name="AutomatedperformancetestingusingJMeterandMaven-Inclosing.."></a>In closing..</h3>

<p>With this information, you can start to make a real difference to your development cycle.  You'll find performance regressions faster and be on you way to code bliss.  If you're interested in some of the processes which you can use to better integrate this cycle, see Andrew Prentice's blog on improving the QA cycle in <a href="http://blogs.atlassian.com/developer/2009/08/testing_and_agile_software_development.html" class="external-link" rel="nofollow">You don't have to be Agile to be agile</a>.</p>

<p align="center"><br><strong><big>Learn more about <a href="http://www.atlassian.com/agile/practices/software-testing.jsp">software testing</a> in an agile development environment</big></strong>
</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=RKPs1WkzAPA:3egQIst0BCg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=RKPs1WkzAPA:3egQIst0BCg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=RKPs1WkzAPA:3egQIst0BCg:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/RKPs1WkzAPA" height="1" width="1"/>]]></content:encoded><description> When I think of Agile, I tend to think of the awesomeness it can bring me as a performance engineer. I see short cycles where the code is usually always stable...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/10/automated_performance_testing_using_jmeter_and_maven.html</feedburner:origLink></item><item><title>Dragon Slayer Supplement: Action Issues with Commit Commands</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/8PM9i-HHa-o/dragon_slayer_supplement_action_issues_with_commit_commands.html</link><category>JIRA</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">James Roper</dc:creator><pubDate>Sun, 11 Oct 2009 16:13:23 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5337</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p>So, you've slayed the Atlassian integration dragon.  But you're still edgy, it was too easy!  You want something harder.  Well I have just the task for you.  Actioning JIRA issues from Subversion commit messages.  Before I go on, let me say, this task is <b>not</b> part of the official Atlassian Dragon Quest.  You will not get another free tshirt if you complete this task.  But, you will get one cool integration feature from Atlassian's products.</p>

<p>Actioning issues from commit messages is a feature that has been available in JIRA Studio for around a year.  The documentation on how to use it (once it's set up) can be found <a href="http://confluence.atlassian.com/display/JIRASTUDIO/Actioning+Issues+via+Commit+Messages">here</a>.  This feature was, from the start, written as a feature that could be used outside JIRA Studio.  However, there was a small amount of effort required to get it to that point.  That effort has never been done, until now.  Well, some of it has been done.  It's still only recommended to be tried by only the bravest of dragon slayers.</p>

<p>First, a bit about how actioning issues with commit commands work.  Atlassian has a little known cross product plugin called the Atlassian Notifier.  This plugin implements WebHooks for Atlassian products.  Using a REST interface, other servers can subscribe to notifications of events on the Atlassian product.  In our case, a servlet in the JIRA FishEye plugin will subscribe to commit notifications from FishEye, this servlet will parse the commit messages, and action JIRA issues accordingly.</p>

<h2>Requirements</h2>

<p>In order to complete this task, you will need:</p>
<ul>
<li>To have completed the Atlassian Dragon Quest</li>
<li>Version 3.1-beta1 of the JIRA FishEye plugin, available <a href="http://maven.atlassian.com/contrib/com/atlassian/jira/plugins/jira-fisheye-plugin/3.1-beta1/jira-fisheye-plugin-3.1-beta1.jar">here</a></li>
<li>A <a href="https://studio.atlassian.com/svn/JST/trunk/webapps/studio-jira/src/main/patches/jira-workflow.xml.patch">patch</a> for the built in JIRA workflow</li>
<li>The FishEye Atlassian Notifier plugin version 2.1-beta1, available <a href="http://maven.atlassian.com/public/com/atlassian/notifier/notifier-fisheye-plugin/2.1-beta1/notifier-fisheye-plugin-2.1-beta1.jar">here</a></li>
<li>A Subversion repository that you can commit to (can be a local filesystem repository)</li>
<li>The <a href="https://addons.mozilla.org/en-US/firefox/addon/2691">Firefox Poster plugin</a></li>
</ul>

<h2>Setup</h2>

<ol>
<li>Install the JIRA FishEye plugin 3.1-beta1 into the <tt>plugins/installed-plugins</tt> directory in the JIRA home directory</li>
<li>From the <tt>atlassian-jira</tt> directory, apply the workflow patch, using the command <tt>patch -p0 &lt; jira-workflow.xml.patch</tt></li>
<li>Restart JIRA</li>
<li>Install the FishEye Atlassian Notifier Plugin into the <tt>var/plugins/user</tt> directory in FishEye</li>
<li>Restart FishEye</li>
<li>Add your Subversion repository to FishEye.</li>
<li>Grant the "charlie" user you created administrator access to FishEye. This can be done by clicking the Administrators link in the FishEye administration menu.</li>
<li>In Firefox, log in to FishEye with the charlie user.  Now, using the Firefox Poster plugin, send a POST request to <tt>{your fisheye base url}/plugins/servlet/notifier/{your repository}/COMMIT</tt>, with content type <tt>application/x-www-form-urlencoded</tt>, and the content <tt>url={your jira base url}/plugins/servlet/commitnotification&authenticationType=TRUSTED_APPS&username=charlie</tt>.  The response code should be 201 Created.</li>
</ol>

<p>You're now ready to go.</p>

<h2>Testing</h2>

<ol>
<li>Create an issue in JIRA</li>
<li>Check out your source code.  If using a file system SVN repository, make sure you specify the --username charlie option.</li>
<li>Make a change, and then commit, with a commit message of <tt>{ISSUEKEY} #resolve It works</tt></li>
</ol>

<p>Within a couple of minutes, your issue should be resolved, and a comment "It works" added to the issue.</p>

<p>If these instructions don't work for you (remember, this task was not for the faint hearted!), then please leave your feedback as comments on this post.</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=8PM9i-HHa-o:nY6IrtXPD-A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=8PM9i-HHa-o:nY6IrtXPD-A:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=8PM9i-HHa-o:nY6IrtXPD-A:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/8PM9i-HHa-o" height="1" width="1"/>]]></content:encoded><description>So, you've slayed the Atlassian integration dragon. But you're still edgy, it was too easy! You want something harder. Well I have just the task for you. Actioning JIRA issues from Subversion...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/10/dragon_slayer_supplement_action_issues_with_commit_commands.html</feedburner:origLink></item><item><title>We're extending Codegeist by a week!</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/NmbD2hKOl4o/were_extending_codegeist_by_a_week.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Nolen</dc:creator><pubDate>Tue, 06 Oct 2009 20:23:00 PDT</pubDate><guid isPermaLink="false">tag:www.atlassian.com,2009:/software/jira/news//2.5329</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><br />
So I was looking at the calendar this morning, and I realized that <a href="http://atlassian.com/codegeist">Codegeist</a> is scheduled to close *this Friday, October 9th*. And I asked myself, "Self, why in the world did you plan to end the contest on a Friday?!" Ending on a Friday eliminates a whole weekend of great hacking time, which something we would normally try to maximize.</p>

<p>So, we've decided to extend the deadline for Codegeist until Sunday night, October 18th. That's just a few days before <a href="http://atlassian.com/atlascamp">AtlasCamp</a>, where were are going to announce the winners. (If you haven't <a href="http://www.atlassian.com/about/events/atlascamp/register.jsp">booked your ticket</a> to AtlasCamp, now is the time!)</p>

<p>Ending on October 18th means that we're going to have to work extra-hard to get the judging done. But it also means that we can give you all two extra weekends to polish your entries. I figured, if you are willing to you pull a few more all-nighters coding, then we can do the same with the judging.</p>

<p>So good luck, everyone and go get your <a href="http://confluence.atlassian.com/display/CODEGEIST/Entries">entries</a> in!</p>

<p><br />
</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=NmbD2hKOl4o:6RdL8TS-IDE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=NmbD2hKOl4o:6RdL8TS-IDE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=NmbD2hKOl4o:6RdL8TS-IDE:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/NmbD2hKOl4o" height="1" width="1"/>]]></content:encoded><description> So I was looking at the calendar this morning, and I realized that Codegeist is scheduled to close *this Friday, October 9th*. And I asked myself, "Self, why in the world...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/10/were_extending_codegeist_by_a_week.html</feedburner:origLink></item><item><title>Codegeist IV: Release Early, Release often</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/4ukxbfCok4g/codegeist_iv_release_early_release_often.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Nolen</dc:creator><pubDate>Wed, 30 Sep 2009 22:44:02 PDT</pubDate><guid isPermaLink="false">tag:www.atlassian.com,2009:/software/jira/news//2.5317</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p>We've got a bit over a week left in <a href="http://atlassian.com/codegeist">Codegeist IV</a>. With over $50k in <a href="http://confluence.atlassian.com/display/CODEGEIST/Prizes">cash and prizes</a> up for grabs, there's a lot riding on this contest.</p>

<p>We've already seen the first few entries go up on the <a href="http://confluence.atlassian.com/display/CODEGEIST/Entries">Entries page</a>. I just wanted to take a second to encourage everyone to get your entries posted as soon as you can. I know that there's a rather overwhelming bias toward procrastination here, but let me urge you to try to overcome that tendency. As I said last year:</p>

<blockquote>The plugins that were submitted early had the benefit of a month of real-world use, feedback, and bug reports. In general, those plugins ended up being substantially more polished and complete than those which appeared at the end. The authors were able to develop detailed documentation and to fix parts which didn't make sense. They put up lots of screenshots. But most importantly, they were able to fix bugs and add features that people requested.

<p>So, my advice is release early, release often. As soon as you have anything workable, put it out and solicit opinions (the forums are a great place for this). The concrete feedback you gain on your Codegeist plugin will be more valuable than the element of surprise that you give up.</blockquote></p>

<p>A little bit of real-world, real-user testing is critical: having a few people (besides yourself) try to install and use a new plugin will go a <em>long</em> toward making sure it also works when the judges try it. So, take advantage of the time left, and get your public out in the open as soon as possible!</p>

<p>Good luck!</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=4ukxbfCok4g:ioQqXJXIQVY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=4ukxbfCok4g:ioQqXJXIQVY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=4ukxbfCok4g:ioQqXJXIQVY:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/4ukxbfCok4g" height="1" width="1"/>]]></content:encoded><description>We've got a bit over a week left in Codegeist IV. With over $50k in cash and prizes up for grabs, there's a lot riding on this contest. We've already seen the...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/codegeist_iv_release_early_release_often.html</feedburner:origLink></item><item><title>Writing Plugins in Scala</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/swnYxcN67q4/writing_plugins_in_scala.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Gilbert</dc:creator><pubDate>Tue, 29 Sep 2009 21:31:17 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5312</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><span class="image-wrap" style=""><img width="50%" src="http://www.scala-lang.org/sites/default/files/newsflash_logo.png" border="0" /></span></p>

<h3><a name="WritingPluginsinScala-WhyScala%3F"></a>Why Scala?</h3>

<p>Scala is currently gaining a lot of traction in the Java community, for a number of reasons. Twitter replaced it's Ruby-based messaging backbone with one written in Scala. It also has a lot going for it as a language, and also compiles to bytecode just as Java does (Martin Odersky wrote both the Scala compiler and the current javac reference compiler).</p>

<h3><a name="WritingPluginsinScala-WhatdoesthislanguagehaveoverJava%3F"></a>What does this language have over Java?</h3>

<p>There's a lot, and some of it certainly looks fairly strange compared to Java. Examples of some of the extras:</p>

<p><b>Methods as first-class objects:</b></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre><span class="linecomment">//won't actually compile due to type constraints, but illustrates the point..</span>
def run(method, param) = { method(param) }
run(System.out.println, "<span class="quote">text</span>")</pre><p><br />
</div></div></p>

<p><b>Closures</b> (of course&#33; And lambda expressions here...)<b>:</b></p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre>var total = 0
<span class="category2">List</span>(1,2,3).foreach { x =&gt; total += x }</pre><p><br />
</div></div></p>

<p><b>Static Typing:</b></p>

<p>No groovy-style fail-at-runtime typing. Everything here is statically typed and checked at compile time. Difference is that things are inferred, otherwise you need to declare the type:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre>var thing = 1
var other : Any = 1
thing = "<span class="quote">new</span>" <span class="linecomment">//fail, was inferred as an integer</span>
other = "<span class="quote">new</span>" <span class="linecomment">//ok, marked as anything (value or ref type)</span></span></pre><p><br />
</div></div></p>

<p><b>Traits:</b></p>

<p>Think interfaces with some code. And yes you can inherit multiple of them. So you effectively get mixins, or sort-of simple multiple inheritance.</p>

<p>There are a lot more; some more simple ones which I've missed from C# are Properties and more sensible super-constructor calling (<tt>class myClass(i : Int) extends mySuper&#40;i){...</tt>}), but I won't go into the rest here. The language supports both OO and functional styles, so at the cost of complexity keeps both camps happy. There is plenty of scope for many Scala posts, and I'll probably do a Friday presentation on it soon, so I'll keep this post primarily concerned with how to write plugins in Scala. If you want more information on the language itself, check out the main <a href="http://www.scala-lang.org/" class="external-link" rel="nofollow">Scala site</a>.</p>

<h3><a name="WritingPluginsinScala-Howdoyoucreateapluginwiththis%3F"></a>How do you create a plugin with this?</h3>

<h4><a name="WritingPluginsinScala-Build"></a>Build</h4>

<p>To build Scala code you can use a Maven2 plugin, and put code in src/main/scala &amp; src/test/scala:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre>&lt;plugin&gt;
    &lt;groupId&gt;org.scala-tools&lt;/groupId&gt;
    &lt;artifactId&gt;maven-scala-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;scala-compile-first&lt;/id&gt;
            &lt;phase&gt;process-resources&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;add-source&lt;/goal&gt;
                &lt;goal&gt;compile&lt;/goal&gt;
            &lt;/goals&gt;
        &lt;/execution&gt;
        &lt;execution&gt;
            &lt;id&gt;scala-test-compile&lt;/id&gt;
            &lt;phase&gt;process-test-resources&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;testCompile&lt;/goal&gt;
            &lt;/goals&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;</pre><p><br />
</div></div></p>

<p>Or you can use your IDE. Idea 9 has a Scala plugin which is fairly good, it supports syntax highlighting, a few basic refactorings and some debugging. I believe Eclipse also has some Scala support.</p>

<h4><a name="WritingPluginsinScala-Deploy"></a>Deploy</h4>

<p>To run a Scala plugin in a standard Java app you simply need to add the runtime jar <em>org.scala-lang:scala-library</em>. Other than that you should be fine, and the code should just work. The main issues you are likely to have are with containers...</p>

<p><br />
<h3><a name="WritingPluginsinScala-Problems"></a>Problems</h3></p>

<h4><a name="WritingPluginsinScala-Velocity%26WebWork"></a>Velocity &amp; WebWork</h4>

<p><br />
<p>Yes, you don't really have to use Velocity, but when writing a Confluence plugin it's pretty tempting. Velocity will work with Scala, but you need to be aware of some things. Here is an example action:</p><br />
<div class="code panel" style="border-width: 1px;"><br />
</p><pre><span class="category1">class</span> ScalaAction <span class="category1">extends</span> ConfluenceActionSupport {
 
 @scala.reflect.BeanProperty
 var myNumber : <span class="category1">int</span> = 21
 
 @scala.reflect.BeanProperty
 var myString : <span class="category2">String</span> = "<span class="quote">testString</span>"
 
 def execute = {
  <span class="category1">try</span> {
   myString = <span class="linecomment">//do something</span>
  } <span class="category1">catch</span> {
   <span class="category1">case</span> e: <span class="category2">Exception</span> =&gt; myString = "<span class="quote">error!</span>"
  }
  
  Action.SUCCESS
 }
}</pre><p><br />
</div></p>

<p>The main thing to notice here is the <tt>@scala.reflect.BeanProperty</tt> annotations. This means that Scala will generate standard getters and setters for these properties, which can then be used by Velocity and WebWork as if you were using Java. Without using this annotation (and if you do), Scala will generate a getter/setter pair as <tt>propertyName()</tt> / <tt>propertyName_eq$(...)</tt> instead of <tt>getPropertyName()</tt> / <tt>setPropertyName(...)</tt>. (Note that you can also annotate the whole class with <tt>@scala.reflect.BeanInfo</tt> to create getters/setters on every property.) I suppose you could still call the Scala getter with <tt>$action.myProperty()</tt>, but you'd lose WebWork injecting the properties.</p>

<h4><a name="WritingPluginsinScala-Spring"></a>Spring</h4>

<p>Spring has identical issues to those above - i.e. using setter injection (mandatory for Confluence plugins-1 plugins) need getters and setters. There are however a few options other than using the above annotations. You could use a <tt>FactoryBean</tt> &#45; although this also causes issues in plugins-1, top level beans are simply created and used, if you want some Spring magic, then it'll need to be a nested bean definition. I hoped that Spring would easily let me redefine the methods which it used to get and set bean properties, however it uses the standard Java <tt>Introspector</tt> to find these methods. Apparently this is being rewritten in Spring 3.0 (I haven't yet tried it) to allow using custom methods, so general Scala support could be added fairly simply with this. Note however that many Scala zealots are not a fan of using a DI framework as Scala is flexible enough to do this itself (like Groovy I suppose), and they often recommend the <a href="http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html" class="external-link" rel="nofollow">Cake Pattern</a> instead.</p>

<p>If you're interested in Scala and want to exchange ideas with other plugin developers, come join us at <a href="http://www.atlassian.com/about/events/atlascamp/">Atlascamp</a>!</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="atlascamp.png" src="http://blogs.atlassian.com/developer/atlascamp.png" width="300px" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=swnYxcN67q4:Xl8KrODAQtg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=swnYxcN67q4:Xl8KrODAQtg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=swnYxcN67q4:Xl8KrODAQtg:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/swnYxcN67q4" height="1" width="1"/>]]></content:encoded><description> Why Scala? Scala is currently gaining a lot of traction in the Java community, for a number of reasons. Twitter replaced it's Ruby-based messaging backbone with one written in Scala. It...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/writing_plugins_in_scala.html</feedburner:origLink></item><item><title>Come to AtlasCamp - but don't take our word for it</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/3E_huhuBPmg/come_to_atlascamp_but_dont_take_our_word_for_it.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jessie Curtner</dc:creator><pubDate>Fri, 25 Sep 2009 10:23:16 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5301</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="atlascamp.png" src="http://blogs.atlassian.com/developer/atlascamp.png" width="546" height="244" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span><br />
AtlasCamp is just around the corner. In fact, there is less then 1 week left before our group room rate expires. So if you're planning on attending, <a href="http://www.atlassian.com/atlascamp">get on it! </a>  If you're not planning on attending, you're nuts.  This is your only chance to get one-on-one time with Atlassian developers and the founders for three days straight. We expect the attendance to be 2-to-1, customers to Atlassians. </p>

<p>Check out what the developers that attended last year are saying.</p>

<p>Matt Doar gave the event <a href="http://toolsmiths.blogspot.com/2009/09/should-you-go-to-atlascamp-hint-yes.html">a great shout-out</a> on his blog. One of Matt's reasons for attending again this year:<br />
<blockquote> <em> Plenty of opportunities to tell the core Atlassian developers and top management exactly what you think of their products</em></blockquote></p>

<p>Chris Kohlhardt from Gliffy is having his whole development team attend this year. Chris just <a href="http://www.gliffy.com/blog/2009/09/24/gliffy-is-attending-atlascamp-2009/">posted a blog</a> that explains why you want to join them. <blockquote><em>It's fun! In addition to learning about the Atlassian plugin ecosystem, we played games, drank beer, and generally had a good time. This isn't some giant conference where nobody knows your name.... since the event is limited to less than 100 people you'll definitely get to meet most of the central figures in the Atlassian development ecosystem.</em></blockquote></p>

<p>Hope to see you there!</p>

<p><strong>The Deets:</strong><br />
Date: October 21 - October 23<br />
Location: <a href="http://www.oceanohalfmoonbay.com/?p=home">The Oceano Hotel and Spa in Half Moon Bay</a><br />
URL: <a href="http://www.atlassian.com/atlascamp">www.atlassian.com/atlascamp</a><br />
</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=3E_huhuBPmg:vTwC_u7im_4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=3E_huhuBPmg:vTwC_u7im_4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=3E_huhuBPmg:vTwC_u7im_4:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/3E_huhuBPmg" height="1" width="1"/>]]></content:encoded><description> AtlasCamp is just around the corner. In fact, there is less then 1 week left before our group room rate expires. So if you're planning on attending, get on it! If...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/come_to_atlascamp_but_dont_take_our_word_for_it.html</feedburner:origLink></item><item><title>Ross Rowe on why you should come to AtlasCamp</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/DZsWewo25_4/ross_rowe_on_why_you_should_come_to_atlascamp.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jonathan Nolen</dc:creator><pubDate>Tue, 22 Sep 2009 21:53:32 PDT</pubDate><guid isPermaLink="false">tag:www.atlassian.com,2009:/software/jira/news//2.5294</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p>Ross just put up a great post about <a href="http://rosspluggedin.wordpress.com/2009/09/22/atlascamp/">why he's coming to AtlasCamp</a> and why you should too.</p>

<p>As Ross says:</p>

<blockquote>AtlasCamp isn’t a boring junket where you sit through endless PowerPoint presentations, it’s fast paced and hands on with lots of coding and technical sessions.

<p>I was fortunate enough to attend last year’s AtlasCamp, and I found it to be a fantastic experience.  It was enlightening to hear from some of the top plugin developers in person about their thoughts and ideas for how they can make Atlassian’s already great products even better.</blockquote></p>

<p>AtlasCamp is the best place to learn about the newest technologies percolating through the Atlassian ecosystem. We don't sit still, and there are a ton of new tools for you to use in extending and enhancing your Atlassian products. Ross agrees:</p>

<blockquote>One of the main reasons that I’ve been developing plugins over the last couple of years is that it allows me to explore technology sets that otherwise I might not get to play with.  Being able to run ideas past both Atlassian and other plugin developers is a great way for me to get valuable advice and feedback.  Personally, I’m really looking forward to hearing about how I can develop plugins using <a href="http://confluence.atlassian.com/display/GADGETS/Using+the+Atlassian+Gadgets+JavaScript+Framework">Gadgets</a>!  Plus I’ll get to hear how I did in this year’s <a href="http://www.atlassian.com/codegeist/">Codegeist</a> competition.

<p>I found the event to be a great way to talk to the other Atlassians/plugin developers in person.  A lot of the communication I’ve had with people has been over email or IM, and it’s always nice to talk face to face!  There was a great sense of camaraderie from everyone there, and I’m really looking forward to seeing both old and new faces and hopefully learning a thing or two!</blockquote></p>

<p>AtlasCamp starts on October 21st in beautiful <a href="http://tinyurl.com/nlfhhu">Half Moon Bay, CA</a>. It's $200 registration for the conference, but it's an experience worth many times that. There will be over 20 Atlassian developers there (including Mike and Scott, Atlassian's co-founders), and we're all excited to hang out with you and listen your feedback. <a href="http://www.atlassian.com/about/events/atlascamp/register.jsp">So sign up today!</a></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=DZsWewo25_4:JpRfWYj1AIE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=DZsWewo25_4:JpRfWYj1AIE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=DZsWewo25_4:JpRfWYj1AIE:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/DZsWewo25_4" height="1" width="1"/>]]></content:encoded><description>Ross just put up a great post about why he's coming to AtlasCamp and why you should too. As Ross says: AtlasCamp isn’t a boring junket where you sit through endless PowerPoint...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/ross_rowe_on_why_you_should_come_to_atlascamp.html</feedburner:origLink></item><item><title>Run your JsUnit tests as normal JUnit4 tests</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/ZlyNK5kR3PE/run_your_jsunit_tests_as_normal_junit4_tests.html</link><category>Java</category><category>Testing</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Shaoting Cai</dc:creator><pubDate>Tue, 22 Sep 2009 10:28:59 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5289</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p>For the Atlassian Gadget project, we use JsUnit and Rhino to make Javascript Unit tests running as part of the Atlassian Gadget Maven build.  However, the JsUnit could only prints test results onto standard out.  And it still seems very hard to fix the jsunit-maven-plugin to use env.js properly.  I could wrote an adapter class that intercept the call to Rhino's main function, and redirect the output to a disk file.  (maybe even format it into Surefire xml format.)  But it would be nicer to take advantage of the existing JUnit, Surefire, Maven integration.</p>

<p>Based on what we have already, I wrote a special JUnit test case and a runner for it.  The runner executes all the JsUnit tests and reports the passing and failure as a JUnit4 test case.</p>

<p><big><strong>One test for all (Js tests)</strong></big></p>

<p>The test case uses its own runner and it only has one test function:</p><pre>@RunWith(RhinoJsUnitRunner.class)
<span class="category1">public</span> <span class="category1">class</span> RhinoJsUnitTest
{
 @Test
 <span class="category1">public</span> <span class="category1">void</span> JsUnitTriggerTest() <span class="category1">throws</span> <span class="category2">IOException</span>
 {
  <span class="category1">final</span> <span class="category2">String</span> path = System.getProperty("<span class="quote">jsunit.entrypoint</span>");
  runJsUnitInRhino(path);
 }
}</pre><p></p>

<p><big><strong>Calling Rhino</strong></big></p>

<p>In the <em>runJsUnitInRhino()</em> function, I created a separate process to run Rhino, because Rhino keeps calling <em>System.exit() </em>which terminates the build process. And the benefit of having a separate process is that I can collect the test result in Rhino's standard output stream. The test result looks like this:</p><pre>Running com.atlassian.gadgets.test.RhinoJsUnitTest
INFO:        [Tue Sep 15 2009 16:15:40 GMT-0700 (PDT)] {ENVJS} adding value to history: file:/Users/scai/Code/AG-svn/trunk/dashboard-plugin/src/test/resources/index.html
INFO:        [Tue Sep 15 2009 16:15:40 GMT-0700 (PDT)] {ENVJS} Sucessfully loaded document at file:/Users/scai/Code/AG-svn/trunk/dashboard-plugin/src/test/resources/index.html
Loading tests.
TestRunner (6 test cases available)
&gt; Starting test suite "<span class="quote">AllTests</span>"
=&gt; Starting test suite "<span class="quote">ParamTest</span>"
-- Running test 1: "<span class="quote">ParamTest.testStandardMessage</span>"
-- Running test 2: "<span class="quote">ParamTest.testMessageWithParameters</span>"
&lt;= Completed test suite "<span class="quote">ParamTest</span>"
=&gt; Starting test suite "<span class="quote">CookieTest</span>"
-- Running test 3: "<span class="quote">CookieTest.testEraseDefinedCookieSucceed</span>"
-- Running test 4: "<span class="quote">CookieTest.testValueSaveReadSucceed</span>"
-- Running test 5: "<span class="quote">CookieTest.testChangeSavedValueSucceed</span>"
-- Running test 6: "<span class="quote">CookieTest.testValueReadUndefinedCookieGetDefaultValue</span>"
&lt;= Completed test suite "<span class="quote">CookieTest</span>"
&lt; Completed test suite "<span class="quote">AllTests</span>"
6 tests successful in 0.024 seconds.</pre><p></p>

<p>Having these information, I can write a simple line parser to retrieve per-test result.  Then the next step is to post the pass/fail event to JUnit and they will all be collected by Surefire.</p>

<p><strong><big>Reporting to JUnit</big></strong></p>

<p>In order to get the Notifier reference, I override the general JUnit4 runner:</p><pre><span class="category1">public</span> <span class="category1">static</span> <span class="category1">class</span> RhinoJsUnitRunner <span class="category1">extends</span> BlockJUnit4ClassRunner
{
 <span class="category1">public</span> RhinoJsUnitRunner(java.lang.Class&lt;?&gt; klass) <span class="category1">throws</span> InitializationError
 {
  <span class="category1">super</span>(klass);
 }
 
 @Override
 <span class="category1">public</span> <span class="category1">void</span> run(RunNotifier notifier)
 {
  runNotifier = notifier;
  super.run(notifier);
 }
}</pre><p></p>

<p>The new runner intercepts the {{run}} method and saves the notifier reference, so that we could do the following event forwarding:</p><pre><span class="category1">private</span> <span class="category1">static</span> <span class="category1">void</span> pass()
{
 <span class="category1">if</span>(currentTest != <span class="category1">null</span>)
 {
  runNotifier.fireTestFinished(currentTest);
  currentTest = <span class="category1">null</span>;
 }
}

<span class="category1">private</span> <span class="category1">static</span> <span class="category1">void</span> fail(<span class="category2">String</span> details)
{
 Failure failure = <span class="category1">new</span> Failure(currentTest, <span class="category1">new</span> <span class="category2">RuntimeException</span>(details));
 runNotifier.fireTestFailure(failure);
}</pre><p></p>

<p>That's all we need to run JsUnit tests as normal JUnit4 tests.</p>

<p><big><strong>SystemProperty in Maven</strong></big></p>

<p>There is one tricky part in starting the Rhino Shell.  Rhino Shell evaluates scripts either from a given file path or from the standard input.  We have to use the file path, because our "test.js" is only an <em>entry point</em>. It loads in more Javascript files using <em>eval()</em> method.  Using standard input will require merging all the required Javascript into one big file.</p>

<p>In order to tell JUnit where to find our <em>entry point</em>, I had to explicitly configure the Surefire plugin in the pom.xml to store the path onto system properties.</p><pre>&lt;plugin&gt;
    &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
    &lt;configuration&gt;
        &lt;systemProperties&gt;
            &lt;property&gt;
                &lt;name&gt;jsunit.entrypoint&lt;/name&gt;
                &lt;value&gt;${basedir}/src/test/javascript/test.js&lt;/value&gt;
            &lt;/property&gt;
        &lt;/systemProperties&gt;
        &lt;junitArtifactName&gt;junit:junit-dep&lt;/junitArtifactName&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</pre><p></p>

<p>I tried setting the value inside the Maven <em>Properties</em> subtree, but the value was not passed to JUnit.  It's only available to references within the pom.xml.</p>

<p>Now, the JsUnit tests are running like normal JUnit4 tests.</p>

<p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blogs.atlassian.com/developer/jsunit.html" onclick="window.open('http://blogs.atlassian.com/developer/jsunit.html','popup','width=785,height=481,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blogs.atlassian.com/developer/assets_c/2009/09/jsunit-thumb-500x306.png" width="500" height="306" alt="jsunit.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=ZlyNK5kR3PE:MatHkssJ4So:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=ZlyNK5kR3PE:MatHkssJ4So:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=ZlyNK5kR3PE:MatHkssJ4So:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/ZlyNK5kR3PE" height="1" width="1"/>]]></content:encoded><description>A way to integrate Javascript unit tests into Maven Surefire JUnit testing and reporting.</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/run_your_jsunit_tests_as_normal_junit4_tests.html</feedburner:origLink></item><item><title>You think being a Web Developer is not enough to win 5,000 bucks? Think again! </title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/iJUZoTCmxSI/you_think_being_a_web_developer_is_not_enough_to_win_5000_bu.html</link><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jens Schumacher</dc:creator><pubDate>Thu, 17 Sep 2009 23:28:04 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.5284</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p>This years <a href="http://www.atlassian.com/codegeist/">Codegeist</a> competition features a new category called <b>Best Theme</b>. It's on the outside what counts for this category. No Java skills required - Confluence can be themed purely with CSS. If you posses the Web Design chops to turn Confluence into a product that would win the Apple design award, you can take home $5,000 and much more.<br />
    
</p><h2>Getting Started</h2>

<p>To get started take a look at our <a href="http://confluence.atlassian.com/display/DOC/Styling+Confluence+with+CSS">documentation</a> and the <a href="http://confluence.atlassian.com/display/DOC/Styling+Tabs+in+Confluence">"Styling Confluence Tabs" tutorial</a>.</p>

<p>For the impatient, here is how to get your CSS into Confluence:</p>

<p></p><ol><li>Log in as the Space Administrator.</li><li>Open the Space Admin page.</li><li>Click 'Stylesheet'.</li><li>Click 'Edit' to change the code in the text field.</li><li>Paste your custom CSS into the text field. (Once the text is saved here, you can make adjustments to it inline.)</li><li>Click 'Save'. The new CSS will be visible on all content pages in the space.</li></ol><div><br /></div><div>If you are no UI wizard, check out our <a href="http://www.atlassian.com/codegeist/">other categories</a> this year. But don't forget to tell your Web Design friends. I am sure they will invite you for a beer or two if they take home the grand prize.&nbsp;</div><div><br /></div><div><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="css-is-awesome.jpg" src="http://blogs.atlassian.com/developer/jens/css-is-awesome.jpg" width="336" height="327" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></span></div><p></p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=iJUZoTCmxSI:vaWPOj54nVg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=iJUZoTCmxSI:vaWPOj54nVg:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=iJUZoTCmxSI:vaWPOj54nVg:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/iJUZoTCmxSI" height="1" width="1"/>]]></content:encoded><description>This years Codegeist competition features a new category called Best Theme. It's on the outside what counts for this category. No Java skills required - Confluence can be themed purely with CSS. If you posses the Web Design chops to turn Confluence into a product that would win the Apple design award, you can take home $5,000 and much more.</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/you_think_being_a_web_developer_is_not_enough_to_win_5000_bu.html</feedburner:origLink></item><item><title>Technical Writing In Agile Software Development - Part 3</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/GAjEm3mK078/technical-writing-in-agile-software-development-part-3.html</link><category>Agile</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Edwin Dawson</dc:creator><pubDate>Thu, 10 Sep 2009 11:08:43 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.2938</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><a href="http://www.atlassian.com/agile"><img src="http://blogs.atlassian.com/news/agile_development_blog_badge-thumb-185x99.png" align="right" class="noborder" alt="Agile software development at Atlassian" style="float: right; margin: 0 0 20px 20px;"></a></p>

<p><strong><big>Part III: Technical Writing Insurgency</big></strong> (<a href="http://blogs.atlassian.com/developer/2009/08/technical-writing-in-agile-software-development-part-1.html">Part I</a> | <a href="http://blogs.atlassian.com/developer/2009/09/technical-writing-in-agile-software-development-part-2.html">Part II</a>)</p>

<p><strong>"Reading the JIRA"</strong></p>

<p>The Atlassian <a href="http://www.atlassian.com/agile/people/technical-writer.jsp">Technical Writers</a> aren't clairvoyants, neither can we use The Force, but those would be really handy abilities in the documentation profession. The next best thing to supernatural powers of prediction is a technique we call "Reading the JIRA". Similar to reading the future in tea leaves, Tarot cards or the creases in your palm, reading the JIRA gives you a sense of things to come and critically, how plans and tasks are changing in the present time. Let me tell you, in an <a href="http://www.atlassian.com/agile">Agile project</a> they'll be twisting and contorting like some mythical serpent in an old, violent legend. </p>

<p>We basically read every change that's going on in Atlassian's <a href="http://www.atlassian.com/software/jira">issue-tracking program</a>, JIRA. As our own software developers are using JIRA itself to track their work which we are in turn documenting, by reading all of this JIRA material we have a  powerful "early-warning" in place, that sometimes makes our prescience seem a little spooky. Milliseconds after a developer updates a spec in JIRA, we're immediately on the instant messenger, asking "How will this affect the documentation?". Sometimes they're a little shocked, responding with "Whoa! Easy there!". This may sound extreme, or perilously close to obsessive behaviour. Still, we've persistently found that by tracking the information flow continuously, monitoring changes <em>Jedi style</em>, we win critical days, hours and minutes that we then have up our sleeves to finish the job in time, no matter what's happened. The flip side of our obsession is that usually, none of the software developers would have thought to inform us about some critical change that turns our priorities upside down. They're bumbling along, hacking away in their IDE, humming blithely to themselves as the crisis bears down over days and weeks. Rather than a scheduled disaster, "Abracadabra"! We've magically got time to finish our work for the release.</p>

<p>At times, reading the JIRA is a lot like tapping the stream-of-consciousness from a high-school programming class packed with testosterone-fuelled egomaniacs, but that's the territory you step into when trying to probe the minds of Top-Gun <a href="http://www.atlassian.com/agile/people/developer.jsp">software developers</a>. Atlassian is most definitely full of those. It's competitive, intellectually vibrant and subject to tidal forces of opinion. </p>

<p><strong>Authoring in Confluence</strong></p>

<p>Another reason we are able to cope with the dynamic documentation work at Atlassian is due to our product, Confluence (which we also dogfood). Confluence is a <a href="http://www.atlassian.com/software/confluence">Wiki</a>, basically like a web server with pages that anyone can edit. For a Technical Writer, where our communication goal is purely informative, Confluence is a powerful solution. With established pages that we've released to the public, we can learn about a problem, find the page, edit the content, have it reviewed and re-publish it to the world in a small number of quick steps. We can have urgent maintenance work on the documentation completed in seconds, when all the pieces fall into place. With the inherent fast-editing capability in Confluence allowing anyone in the company to edit the pages, my subject matter experts are brought much closer to the content. It only takes a few minutes of their time and they can make all necessary changes immediately. This adds obvious bonuses to technical accuracy and speed of review (enabling multiple, iterative reviews to take place). Of course, professional writers are still essential to bring refinement, structure and enterprise standards of communication to the material. </p>

<p>If you're a Technical Writer about to embark upon an Agile adventure, you're in for an exciting ride. Throw out the rulebook, publish in a Wiki and get your developers using a quality issue tracker. </p>

<p>Finally, I will leave you with the words of Governor Bibble. Remember: "<em>A disruption in communications can mean only one thing... invasion!</em>"</p>

<p>Ed Dawson is the Technical Writing Team Leader at Atlassian.<br />
<br><p align="center">This is the final installment in a three part agile technical writing blog series: <a href="http://blogs.atlassian.com/developer/2009/08/technical-writing-in-agile-software-development-part-1.html">Agile Technical Writing - <strong>Part I</strong></a> | <a href="http://blogs.atlassian.com/developer/2009/09/technical-writing-in-agile-software-development-part-2.html">Agile Technical Writing - <strong>Part II</strong></a></p>

<p align="center">
<br>
<big><strong>Sarah Maddox discusses technical writing in an agile  environment</strong></big>
<br><br><object width="640" height="391" type="application/x-shockwave-flash" name="ep_player" id="ep_player" data="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoleumgw4a33%2Fconfig.xml&autoplay=false"><param value="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoleumgw4a33%2Fconfig.xml&autoplay=false" name="movie"/><param value="always" name="AllowScriptAccess"/><param value="false" name="allowfullscreen"/><embed width="640" height="391" type="application/x-shockwave-flash" src="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoleumgw4a33%2Fconfig.xml&autoplay=false" name="ep_player" mce_src="http://cdn.episodic.com/player/EpisodicPlayer.swf?config=http%3A%2F%2Fcdn.episodic.com%2Fshows%2Fl6ica3s712x1%2Fmoleumgw4a33%2Fconfig.xml&autoplay=false" id="ep_player" allowscriptaccess="always" allowfullscreen="false"/><a mce_href="http://analytics.episodic.com/download/emoleumgw4a33/f20/technical-writer-on-writing-for-and-agile-company.mp4" href="http://analytics.episodic.com/download/emoleumgw4a33/f20/technical-writer-on-writing-for-and-agile-company.mp4"><img width="640" height="360" border="0" src="http://cdn.episodic.com/shows/assets/480/a7652.jpg" mce_src="http://cdn.episodic.com/shows/assets/480/a7652.jpg"/></a></object><br><br><strong><big>Learn more about <a href="http://www.atlassian.com/agile/people/technical-writer.jsp">technical writing and agile development</a> inside Atlassian</big></strong>
</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=GAjEm3mK078:U-dBaAGXolY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=GAjEm3mK078:U-dBaAGXolY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=GAjEm3mK078:U-dBaAGXolY:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/GAjEm3mK078" height="1" width="1"/>]]></content:encoded><description>The Atlassian Technical Writers aren't clairvoyants, neither can we use The Force, but those would be really handy abilities in the documentation profession.</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/technical-writing-in-agile-software-development-part-3.html</feedburner:origLink></item><item><title>Checking in on red helps keep the build green</title><link>http://feedproxy.google.com/~r/AtlassianDeveloperBlog/~3/q8MPwWtRcI4/checking_in_on_red_helps_keep_the_build_green.html</link><category>Bamboo</category><category>JIRA</category><category>Software engineering</category><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Brad Baker</dc:creator><pubDate>Wed, 09 Sep 2009 11:12:48 PDT</pubDate><guid isPermaLink="false">tag:blogs.atlassian.com,2009:/developer//14.2943</guid><content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[
        <p><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="Stop_Light.jpg" src="http://blogs.atlassian.com/developer/pictures/Stop_Light.jpg" width="300" height="316" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></span></p>

<p>For the last 3-4 weeks the JIRA team has been following a development process where we are allowed to check in...<strong>when the build is broken</strong>.</p>

<p>Heresy...lunacy...insanity...</p>

<p>Well it turns out that it helps <span style="color:#28532D">keep the build green.</span></p>

<p>And here is why...<strong>build latency. </strong></p>

<p>I am defining <strong>build latency</strong> as the time from checking-in a change, finding out your broke the build and then checking in another change and knowing that you have fixed the build.</p>

<p><br />
<h2>4 Months Ago</h2></p>

<p>About 4 months ago our development process rule was that you must not check when the build is broken and you must not check in and go home unless you know it has passed. </p>

<p>Our unit tests and web functional tests were taken about 7 minutes and 2 1/2 hours to run respectively.  Therefore if some one did break the build, it took at a minimum 2 1/2  but more like 3 1/2 hours to fix. </p>

<p>You had to find out who broke things, find out why, find the person and then get a fix in.  And then you had to wait another 2/12 hours to see if the fix worked. </p>

<p>Because of this build feedback latency, we as a team ended up checking-in in a very synchronized way (say at 10.00am and then at say 3.00pm if on wanted to go home by 5.30pm) and because in a team of 12 people, some one is bound to break something at least once a day, we could check-in changes at most once, maybe twice a day. </p>

<p>Because you are only checking in once or twice a day, the changes tend to be larger and hence more likely to break the build.  It becomes a bit of a negative feedback system of broken builds.</p>

<p>During this period the average time of breaking the build to it going green again could be about 2-4 hours but sometimes it was days.</p>

<p>People would then break the rules and check in when the build was broken, but this would often just confuse the situation and extend the build latency.</p>

<p><br />
<h2>2 Months Ago</h2></p>

<p>The long build times had been bubbling away for a long time and during dev speed week, Chris M and others did the work to split the build into a series of batches.</p>

<p>So instead of running 2000 tests in serial over 2/12 hours,  we split them into 15 batches and ran them in parallel using the Bamboo Elastic Cloud support to create 15 remote agents.</p>

<p>This resulted in build run times of between 12-40 minutes.  (Splitting into an even number of batches doesn't mean an even number of test run times it seems)</p>

<p>This reduced the build latency down to a more manageable level.  Now you found out quicker that the build was broken but it was still talking about 1 hour to 1 1/2 hours to fix a broken build and the others in the team could not check in for that time period.</p>

<p><br />
<h2>1 Month Ago</h2></p>

<p>So about a month ago we dropped the rule about checking in when the build is broken.  </p>

<p>However there are a series of caveats. </p>

<ul>
    <li>When the one of the batches breaks, we as a team have to work out who broke it.
          We have 15 batches of builds and hence you may have broken 1 or more batches</li>
    <li>That person is then responsible to fix the build batch(es) in question. </li>
    <li>The other team members are free to check in while this happens.</li>
    <li>If the build continues to stay broken, or gets more broken (eg more and different tests start breaking) then a freeze is put in place to sort it out.</li>
    <li>Jed was appointed build champion to keep an eye on the situation and to chase up people.</li>
</ul>

<p>The end result is that the build does not stay broken for long and the rest of the team can continue to make small changes to the code base. </p>

<p>Small changes are less likely to break the build and hence it tends to stay green for longer.  Its a more of a positive feedback system.</p>

<p>We also added another little feature into the functional test framework that also helps. </p>

<p>We keep track of the tests that have failed ourselves instead of relying on JUnit/Bamboo test results.  At the end of each test case run, we output a log message that tells us the state of the system. </p>

<p>It looks a bit like this :</p>

<pre>
===FTC Finished : TestSystemFieldLiterals.testType #2164 of 2361 (91.66%) : Errors 1 (0.042%)
   : Run time 4.59 seconds : Suite time 12656.18 seconds : HTTP Count 40
   : HTTP Time 2732ms : HTTP 100th 1637ms : HTTP 90th 88ms : HTTP 50th 18ms : HTTP Ave 0.07 ms/request
   : Max Mem 365428736 : Total Mem 365428736  : Free Mem 125712536
  1 test(s) failing so far :
      TestIssueDreams.testIssueLevelSecurity
</pre>

<p>You can tell by looking at the Bamboo live logs if the build is going to fail.  If the log tells you that the one or more tests has failed, you can start working on the fix and check it in before the batch build finishes and hence reduce the build latency.</p>

<p><br />
<h2>Conclusion</h2></p>

<p>Conventional thinking is that a team should not check-in while the build is broken.  The thinking goes that that you will not be able to keep track of the changes your team makes otherwise.  </p>

<p>We have found that you can make changes while the build system is broken, within reasonable limits.</p>

<p>And the longer your build latency,  the greater the payback of this type of development process.</p>
        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=q8MPwWtRcI4:BTznHe9QwnQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?a=q8MPwWtRcI4:BTznHe9QwnQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AtlassianDeveloperBlog?i=q8MPwWtRcI4:BTznHe9QwnQ:V_sGLiPBpWU" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AtlassianDeveloperBlog/~4/q8MPwWtRcI4" height="1" width="1"/>]]></content:encoded><description> For the last 3-4 weeks the JIRA team has been following a development process where we are allowed to check in...when the build is broken. Heresy...lunacy...insanity... Well it turns out that...</description><feedburner:origLink>http://blogs.atlassian.com/developer/2009/09/checking_in_on_red_helps_keep_the_build_green.html</feedburner:origLink></item></channel></rss>
