<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>BEKK Open &#187; Kvalitet og testing</title>
	<atom:link href="http://open.bekk.no/category/bekk/tech/kvalitet-og-testing/feed/" rel="self" type="application/rss+xml" />
	<link>http://open.bekk.no</link>
	<description>Et innblikk i hva som skjer i BEKK</description>
	<lastBuildDate>Fri, 11 May 2012 16:31:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Erfaringer fra testdrevet JavaScript</title>
		<link>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/</link>
		<comments>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 00:10:40 +0000</pubDate>
		<dc:creator>Snorre Brandstadmoen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[web sockets]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=8033</guid>
		<description><![CDATA[Magnar Sveen gir en glimrende introduksjon til testdrevet JavaScript-utvikling i screencast-serien &#8220;Zombier, mafia og testdrevet utvikling&#8221;, zombietdd.com. Etter å ha fulgt med på denne i høst, ble jeg inspirert til å gjøre noe tilsvarende selv og bestemte meg for å utvikle en enkel applikasjon, der jeg benytter TDD-metodikk og tilhørende verktøy. iTouch App&#8217;en som skal [...]]]></description>
			<content:encoded><![CDATA[<p>Magnar Sveen gir en glimrende introduksjon til testdrevet JavaScript-utvikling i screencast-serien &#8220;Zombier, mafia og testdrevet utvikling&#8221;, <a href="http://zombietdd.com" target="_blank">zombietdd.com</a>. Etter å ha fulgt med på denne i høst, ble jeg inspirert til å gjøre noe tilsvarende selv og bestemte meg for å utvikle en enkel applikasjon, der jeg benytter TDD-metodikk og tilhørende verktøy.</p>
<p><span id="more-8033"></span></p>
<h2>iTouch</h2>
<p>App&#8217;en som skal lages er et spill, hvor poenget er å taste en gitt tekst feilfritt, raskest mulig. Spillet skal støtte flere samtidige spillere, og alle spillere skal fortløpende se hvordan konkurrenter ligger an underveis, samt status på egen tasting i form av fargekoding av tastet tekst.</p>
<p>Jeg ser for meg en arkitektur der vi kjører JavaScript på server, JavaScript+HTML på klienter, og sanntidsoppdatering av konkurrentstatus over Web Sockets.</p>
<p style="text-align: center"> <a href="http://open.bekk.no/wp-content/uploads/2012/02/overordnet_arkitektur.png"><img class="size-full wp-image-8041 aligncenter" src="http://open.bekk.no/wp-content/uploads/2012/02/overordnet_arkitektur.png" alt="Overordnet arkitektur" width="722" height="494" /></a></p>
<p>Tanken er at på hvert tastetrykk, sender klienten inntastet tekst til serveren for validering. Serveren sender så tilbake et statusobjekt som sier noe om hvorvidt tastet tekst er feil, hvor mye av tekst som gjenstår osv. Det blir så opp til klienten presentere denne statusen til brukeren.</p>
<h2>Litt om teknologi</h2>
<p>Til Web Sockets-kommunikasjonen skal jeg bruke rammeverket <a href="http://nowjs.com" target="_blank">NowJS</a>, som er ganske fascinerende. Det lar deg synkronisere JavaScript-variabler og -funksjoner mellom klient og server, slik at man kan kalle funksjoner på server direkte fra klient, og faktisk også funksjoner definert på klient(er) direkte fra server. NowJS baserer seg på veletablerte SocketIO.</p>
<p>Serverkoden kjører på <a href="http://nodejs.org" target="_blank">Node.js</a>, som er blitt en defacto plattform for serverside JavaScript.</p>
<h2>Testdrevet utvikling</h2>
<p>I JavaScript er det p.t. en rekke testrammeverk tilgjengelig. Jeg har valgt å bruke <a href="http://pivotal.github.com/jasmine" target="_blank">Jasmine</a>, mest fordi jeg liker BDD-syntaksen, og at man kan benytte rammeverket til å teste både klient- og serverkode. I dag ville jeg nok gått for <a href="http://busterjs.org" target="_blank">Buster.JS</a>, men mer om Buster senere.</p>
<p>Man kan fint kjøre Jasmine-tester <a href="https://github.com/pivotal/jasmine/blob/master/lib/jasmine-core/example/SpecRunner.html" target="_blank">standalone i en nettleser</a>, men det er fornuftig å benytte seg av en test runner, eksempelvis <a href="http://code.google.com/p/js-test-driver" target="_blank">JS Test Driver</a>. Bloggpost’en til kollegaer Torstein og Børge: <a title="Getting started with JS and TDD" href="http://open.bekk.no/getting-started-with-js-and-tdd/" target="_blank">”Getting started with JS and TDD”</a>,  gir en grundig innføring i hvordan Jasmine er i bruk, samt hvordan man integrerer med JS Test Driver.</p>
<p>Det avgjørende her er å få lastet ned riktige biblioteker, lagt disse inn i en fornuftig <a href="https://gist.github.com/1747920" target="_blank">mappestruktur</a>, og fått satt opp en <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/jsTestDriver.conf" target="_blank">jsTestDriver.conf</a>-fil til å reflektere denne.  I tillegg kan det være fornuftig å installere &#8220;jstdutil&#8221;. Dette verktøyet lar deg kjøre kommandoene &#8220;jstestdriver&#8221; og &#8220;jsautotest&#8221; fra kommandolinja. Sjekk siden til Christian Johansen for <a href="http://cjohansen.no/en/javascript/jstdutil_a_ruby_wrapper_over_jstestdriver" target="_blank">installasjonsbeskrivelse</a>.</p>
<p>Prosjektet mitt benytter altså Jasmine som testrammeverk, og JS Test Driver for å kjøre testene. Når disse tingene er på plass, er man klar til å skrive første test!</p>
<h2>Første test</h2>
<p>Dette blir litt som å skrive første setningen i en bok, eller i denne bloggposten for den saks skyld. Jeg tenker det enkleste å teste i min kode måtte være mekanismen som validerer inntastet tekst. Jeg ser for meg at vi oppretter en scoringobjekt som tar inn en tekst, og returnerer et statusobjekt som sier noe om hvilke bokstaver i teksten som evt. er feil.</p>
<p>Vi spesifiserer forventet oppførsel i filen spec/scoring.spec.js:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should validate text with 2 errors&quot;</span><span style="color: #339933;">,</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;DeTte Er en test&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span>scoring.<span style="color: #660066;">validate</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeDefined</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> results <span style="color: #339933;">=</span> scoring.<span style="color: #660066;">validate</span><span style="color: #009900;">&#40;</span>originalText<span style="color: #339933;">,</span> typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">errors</span>.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">errors</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">6</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>og kjører kommandoen ”jstestdriver –tests all –reset”, eller enda bedre ”jsautotest”. Vi får beskjed om å opprette scoring-modulen i namespacet TDD, med funksjonen &#8220;validate&#8221;. Og etter litt TDD’ing ender vi opp med en mer eller mindre komplett <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/spec/server/scoring.spec.js" target="_blank">scoring.spec.js</a>  med tilhørende implementasjon <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/scoring.js" target="_blank">scoring.js</a>.</p>
<h2>Arkitektur</h2>
<p>Før vi går videre med tester, kan vi titte litt på kodearkitektur. I tillegg til scoring-modulen, trenger vi funksjonalitet for å administrere selve spillets gang. La oss gi denne modulen navnet &#8220;game&#8221;. På klientsiden trenger vi en modul som styrer kommunikasjonen med server og oppdatering av skjermbilder; game_controller.js</p>
<p>Hvis vi skisserer opp systemet, så har vi et avhengighetsbilde som ligner dette:</p>
<p>&nbsp;</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/02/javascriptarkitektur.png"><img class="aligncenter size-full wp-image-8059" src="http://open.bekk.no/wp-content/uploads/2012/02/javascriptarkitektur.png" alt="" width="360" height="427" /></a></p>
<p>Vi vet at game benytter NowJS-rammeverket for å formidle sanntidsinformasjon, i tillegg til scoringmodulen for å kalkulere status. Samtidig skal game_controller.js kommunisere med game.js vha. NowJS.</p>
<p>Når man nå skal sette sammen disse bitene, er det viktig å tenke at de skal være <strong>løst koblet</strong>. Dette kan man få til ved å spesifisere eksterne avhengigheter ved opprettelse av modulene. F.eks., får game.js <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC17" target="_blank">sprøytet inn en referanse til scoring</a> og <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC20" target="_blank">NowJS</a> når den blir opprettet, og kode for å opprette et game-objekt blir:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> game <span style="color: #339933;">=</span> TDD.<span style="color: #660066;">game</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    originalText<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;En tekst&quot;</span><span style="color: #339933;">,</span>
    scoring<span style="color: #339933;">:</span> TDD.<span style="color: #660066;">scoring</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    everyone<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Dette gjør det lett å enhetsteste game.js, da man enkelt kan stubbe/mocke disse avhengighetene.</p>
<h2>Mer testing</h2>
<p>Nå har det liten hensikt å gå i gjennom all kildekode og tester i teksten her, men vi skal se litt mer på hvordan utvalgt funksjonalitet er implementert og testet.</p>
<p>Når det gjelder game-modulen, skal denne bla. ha funksjonalitet for å</p>
<ul>
<li>registrere deltakere</li>
<li>sette i gang en ny omgang</li>
<li>distribuere forløpende status til alle deltakere</li>
</ul>
<p>Hvis vi ser nærmere på det siste punktet, så skal status sendes fortløpende til alle deltakerne i sanntid over Web Sockets vha. NowJS. Web Sockets-kommunikasjonen er fullstendig abstrahert bort av rammeverket, og alt man trenger å gjøre er å legge til funksjoner i det spesielle ”<a href="http://nowjs.com/doc/nowjs" target="_blank">now</a>”-objektet som blir synkronisert mellom server og klient. Rammeverket fungerer slik at man kan adressere server via now-objektet på klienten, samt adressere alle klienter via everyone.now-objektet fra serveren.</p>
<p>Når man vet hvordan dette rammeverket fungerer, er man i stand til å spesifisere testen:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should validate text and distribute scores upon validation request&quot;</span><span style="color: #339933;">,</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er en&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">status</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;errors&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;percentage&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">98</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">scoring</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;validate&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">andReturn</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'receiveScores'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">receiveScores</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalledWith</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
        clientId<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;123&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #000066;">name</span><span style="color: #339933;">:</span> undefined
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Her bruker vi <a href="https://github.com/pivotal/jasmine/wiki/Spies" target="_blank">spy-egenskapene</a> til Jasmine, til å legge til en forventning om at når man kaller ”validate”-funksjonen på serveren, så skal ”receiveScores”-funksjonen kalles på alle klienter.</p>
<p>Selve this.everyone.now er en stub vi selv spesifiserer:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    now<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        validate<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        receiveScores<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>clientId<span style="color: #339933;">,</span> score<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        startGame<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        displayTextToBeTyped<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        hideStartButton<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        showStartButton<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        clearText<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        gameOver<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        user<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
            clientId<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;123&quot;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Igjen, er det bare å <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC85" target="_blank">implementere spesifikasjonen</a> og kjøre testene:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should massage original text
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should validate text and distribute scores upon validation request
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should NOT end game when text is errornous
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should end game when text is <span style="color: #7a0874; font-weight: bold;">complete</span> with no errors
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should start game on request
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should validate typed text
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should validate text with <span style="color: #000000;">2</span> errors
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is incomplete
Total <span style="color: #000000;">10</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">10</span>; Fails: <span style="color: #000000;">0</span>; Errors: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">8.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  Firefox <span style="color: #000000;">10.0</span> Mac OS: Run <span style="color: #000000;">10</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">10</span>; Fails: <span style="color: #000000;">0</span>; Errors <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">8.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<h2>Hva med klienten?</h2>
<p>Det er like enkelt å teste klientkode som serverkode, selv om man må hanskes med en DOM. Det avgjørende her er å gjøre klientkoden ”unobtrusive” og ikke mikse JavaScript og HTML-markup mer enn nødvendig.</p>
<p>Vi kan begynne med å tenke litt på hvordan markup’en på klienten skal se ut. Da spillet går ut på taste en gitt tekst, trenger vi i hvert fall et editerbart felt, og et element til å presentere tekst som skal tastes. I tillegg kan vi legge til en knapp for å starte en omgang, samt et element for å vise progress bars. Grensesnittet kan f.eks. se slik ut:</p>
<p style="text-align: left"><a href="http://open.bekk.no/wp-content/uploads/2012/02/gui.png"><img class="aligncenter size-full wp-image-8064" src="http://open.bekk.no/wp-content/uploads/2012/02/gui.png" alt="" width="618" height="539" /></a><br />
med tilhørende HTML:</p>
<pre>&lt;!DOCTYPE&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;div id="wrapper"&gt;
      &lt;h1&gt;iTouch&lt;/h1&gt;
      &lt;input id="name" type="text" placeholder="Skriv inn navnet ditt her og trykk ENTER"/&gt;
      &lt;button id="startButton"&gt;Start ny omgang (vent til alle er klare da)&lt;/button&gt;
      &lt;div id="text-to-be-typed"&gt;&lt;/div&gt;
      &lt;div id="typed-text" contenteditable="true"&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Med disse antakelsene, kan vi utvikle klientlogikken – <strong>test først</strong>.</p>
<p>Eksempelvis kan vi spesifisere at spillet skal startes når noen klikker på ”Start ny omgang”-knappen på følgende vis:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should do start game when start button is clicked&quot;</span><span style="color: #339933;">,</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;startGame&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span>.<span style="color: #660066;">trigger</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">startGame</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span><span style="color: #009900;">&#41;</span>.<span style="color: #000066; font-weight: bold;">is</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">':hidden'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeTruthy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Denne testen spesifiserer at startGame-funksjonen skal kalles, og at knappen skal skjules.<br />
$(this.startButton) er et jQuery-wrappet element som er definert slik:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;button&gt;&lt;/button&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    id<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;startButton&quot;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">appendTo</span><span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>og <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/spec/client/game_controller.spec.js#LC45" target="_blank">sprøytet inn i game_controller-modulens create-funksjon</a>.</p>
<p>Slik kan vi fortsette; ta f.eks. koden som tester at tekst fargelegges korrekt. Ganske avansert GUI-messig, og ganske enkelt å teste da man kan simulere nettleser-eventer, kjøre css-spørringer osv.:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should color text upon text validation and update progress bar&quot;</span><span style="color: #339933;">,</span>
<span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> self <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> originalText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er en test&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er En&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> errorIndex <span style="color: #339933;">=</span> <span style="color: #CC0000;">9</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> clientId <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;123&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;validate&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">andCallFake</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        self.<span style="color: #660066;">now</span>.<span style="color: #660066;">receiveScores</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            clientId<span style="color: #339933;">:</span> clientId<span style="color: #339933;">,</span>
            <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Snorre&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #3366CC;">&quot;errors&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>errorIndex<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;percentage&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">95</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">displayTextToBeTyped</span><span style="color: #009900;">&#40;</span>originalText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">typedTextElement</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">typedTextElement</span>.<span style="color: #660066;">trigger</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;keyup&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">validate</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(1)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(0, 128, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>errorIndex <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(255, 0, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>typedText.<span style="color: #660066;">length</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(0, 0, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">wrapperElement</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#&quot;</span> <span style="color: #339933;">+</span> clientId<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;value&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">95</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Når man lager JavaScript-koden &#8220;unobtrusive&#8221; (i mangel av et bedre norsk ord), blir man kvitt all spagettikode man ofte ser i $(document).ready(), og sitter igjen med en <strong>ryddig</strong> <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/public/index.html" target="_blank">index.html</a>.</p>
<h2>Hmmm, hvorfor kjører vi alle testene i Firefox?</h2>
<p>Inntil nå, har vi kjørt klientestene og servertesten i kontekst av en nettleser via JS Test Driver. Da vi at vet at serverkoden skal kjøre på Node, gir det ikke mening å la ymse <a href="http://en.wikipedia.org/wiki/JavaScript_engine#JavaScript_engines" target="_blank">nettleser-JavaScript-motorer</a> - og ikke Nodes Google V8-baserte kjøretidsmiljø, tolke koden vår. Vi kan bote på dette ved å kjøre server testene med <a href="https://github.com/mhevery/jasmine-node" target="_blank">jasmine-node</a>. Dette er en Node.js-modul, som installeres med <a href="http://npmjs.org/" target="_blank">npm</a> (som nå bundles med Node-installasjonen). Da kan vi kjøre servertestene våre med:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">~<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>faggruppe<span style="color: #000000; font-weight: bold;">/</span>iTouch<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">git</span>::master<span style="color: #7a0874; font-weight: bold;">&#41;</span>:➔ jasmine-node spec<span style="color: #000000; font-weight: bold;">/</span>server <span style="color: #660033;">--verbose</span>
Started
..........
Spec Game
  it should massage original text
  it should validate text and distribute scores upon validation request
  it should NOT end game when text is errornous
  it should end game when text is <span style="color: #7a0874; font-weight: bold;">complete</span> with no errors
  it should start game on request
Spec Validation of text and scoring
  it should validate typed text
  it should validate text with <span style="color: #000000;">2</span> errors
  it should calculate score when typed text is <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
  it should calculate score when typed text is <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
  it should calculate score when typed text is incomplete
Finished <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">0.005</span> seconds
<span style="color: #000000;">2</span> tests, <span style="color: #000000;">24</span> assertions, <span style="color: #000000;">0</span> failures</pre></div></div>

<p>Dette fremprovoserer også det faktum at vi er nødt til å gjøre om scoring.js-modulen til å være <a href="http://www.commonjs.org/">Node/CommonJS</a>-kompatibel, da Node krever dette. Dette gjøres ved å legge til disse linjene i scoring:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> module <span style="color: #339933;">===</span> <span style="color: #3366CC;">'object'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> TDD.<span style="color: #660066;">scoring</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Man kan da &#8220;hente&#8221; ut en referanse til scoring-modulen som en vanlig Node-modul slik:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">TDD.<span style="color: #660066;">scoring</span> <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;./src/server/scoring&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>Buster</h2>
<p>Her kommer vi tilbake til <a href="http://busterjs.org/" target="_blank">Buster.js</a>. I tillegg til å være et flott testrammeverk på andre måter, gir Buster deg mulighet til å <a href="http://busterjs.org/docs/hybrid-testing/" target="_blank">kjøre klient- og servertester med samme test runner</a>. Buster.js er snart ute av beta, blir spennende å sjekke det ut nærmere.</p>
<h2>Skru alt sammen</h2>
<p>Når all JavaScript-logikken er ferdig implementert, gjenstår konfigurasjon av Node, slik at vi kan begynne å teste spillet. All denne konfigurasjonen gjøres i filen <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/app.js" target="_blank">app.js</a>. Her ser vi hvordan vi oppretter et game-objekt, med alle dets avhengigheter.</p>
<p>Her er et artig lite avbrekk i en ellers hektisk prosjekthverdag:<br />
<span style="text-align:center; display: block;"><a href="http://open.bekk.no/erfaringer-fra-testdrevet-javascript/"><img src="http://img.youtube.com/vi/kXEiXN3ezFI/2.jpg" alt="" /></a></span></p>
<h2>Oppsummering</h2>
<p>Å komme fra en typisk hverdag der jeg skriver &#8220;mvn clean install&#8221; altfor mange ganger i løpet av en dag, er det utrolig frigjørende å se hvor raskt disse JavaScript-testene kjører. Når man først kommer inn i det, er JavaScript en fornøyelse å jobbe med, spesielt med tanke på egenskapene ved språket. TDD i JavaScript er definitivt ikke vanskelig, og det er like greit å lære seg teknikkene først som sist.</p>
<h3>On a side note:</h3>
<p>Magnar Sveen snakker om zombietdd-prosjektet sitt <strong>i morgen på </strong><a href="http://www.meetup.com/framsia/events/49837362/" target="_blank"><strong>Framsia at CiA 2012 &#8211; Responsive, realtime and Zombies</strong>!</a> Meetup&#8217;en omhandler forøvrig Web Sockets og Node.js, så det er ikke helt urelatert til det som blir tatt opp her!</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting started with JS and TDD</title>
		<link>http://open.bekk.no/getting-started-with-js-and-tdd/</link>
		<comments>http://open.bekk.no/getting-started-with-js-and-tdd/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 07:00:26 +0000</pubDate>
		<dc:creator>Torstein Nicolaysen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[jasmine]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[jstestdriver]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test-driven development]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6436</guid>
		<description><![CDATA[Introduction Are you working on unmaintainable JavaScript code? Are you afraid to make changes to your 5000+ lines long JS file? If so, you&#8217;ve probably not written tests or done TDD. Fear not! Read on, and we will show you how to get started with writing tests and setting up the needed tools. We will [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Are you working on unmaintainable JavaScript code? Are you afraid to make changes to your 5000+ lines long JS file? If so, you&#8217;ve probably not written tests or done TDD. Fear not! Read on, and we will show you how to get started with writing tests and setting up the needed tools. We will show by example how to create a small, yet complex, JS web application using TDD.</p>
<p>JavaScript is becoming increasingly popular for developing full-fledged applications &#8211; both <a href="http://en.wikipedia.org/wiki/Nodejs">server</a> and client side. Looking at the current trend of how JS is used, we can see that it’s being used for business critical applications and large-scale applications. With all this popularity and extensive use, we are under the impression that the testing and quality focus is lagging behind.</p>
<p>After reading this blog post, you will know how to get started with JS TDD using tools and frameworks we consider easy to use and relatively mature. If you already know <strong>why</strong> you should test your JS code, feel free to skip the background.</p>
<p>If you want to take a closer look at the example application, feel free to check out the entire project from GitHub @ <a href="http://github.com/bekk/jstdd">http://github.com/bekk/jstdd</a>.</p>
<h2>Background</h2>
<p><img class="size-full wp-image-7874" src="http://open.bekk.no/wp-content/uploads/2012/01/JavaScript-logo.png" alt="The JavaScript logo" width="192" height="192" align="right" /> JavaScript has received a popularity boost from browser vendor’s quest to write the fastest JS engine, as well as the popular programming language <a href="http://en.wikipedia.org/wiki/Nodejs">node.js</a>. In addition, jQuery has simplified the way we interact with the DOM and smooths over annoying browser differences &#8211; making JS more accessible for everyday developers. Focus have been primarily on producing functionality, and not on testing and good design/clean code. We believe that one reason is the lack of standardized or commonly available testing tools and frameworks. Another reason might be that traditionally JS have been written by UI and UX developers, who’s focus have been primarily on functionality &#8211; not on <em>Clean Code</em> and testability.</p>
<p>JS and all other dynamic programming languages is in dire need of tests since there is no compile-time checking. Tests can be used to ensure that the application <strong>behaves as expected</strong>, and gives developers confidence to make changes to existing code. Despite the obvious need for testing, many developers skimp on writing tests when developing large JS applications. All the advantages of TDD that applies for other programming languages, also applies for JS. Who does not want testable, maintainable, readable, well-designed, modular and working code? It’s well established that TDD has positive effects on code quality (read the chapter on TDD by Robert C. Martin in <a href="http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073">The Clean Coder</a>).</p>
<p>Other popular programming languages like Java and C# have mature and well-documented testing-tools. At the time of writing, JS has <a href="http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript">several testing frameworks available</a>, but only a handful mature. Looking at the options, no one really stands out as a clear choice. To make things worse, getting started with JavaScript TDD can be challenging. There are so many ways of going about setting up a complete test-environment for JS. We have looked into this and had some experience with what works and what doesn&#8217;t.</p>
<h2>The runner</h2>
<p><a href="http://code.google.com/p/js-test-driver/">JsTestDriver</a> is (as it’s name implies) a tool that let you run your JS tests. You can run your tests directly from your favorite IDE (at least in theory) to get into your TDD rhythm. It runs from the command line and even on your continuous integration server. In our examples we’ll be running it from the command line.</p>
<p>A quote from their home site says it all: “The goal of JS Test Driver is to make JavaScript unit test development as seamless as and easy as Java unit tests.”</p>
<p>JsTestDriver supports testing in different browsers through capturing browsers as a slave machines. It includes it’s own limited assertion framework, but also supports add-ons, which opens for a wide range of <a href="http://code.google.com/p/js-test-driver/wiki/XUnitCompatibility">third party</a> assertion frameworks. We will be using Jasmine BDD through an adapter.</p>
<p>As with everything else, there is room for improvement. JsTestDriver&#8217;s configuration can sometimes be too simple, and advanced users may feel limited. In our simple example it works great, but expect some issues when scaling up. As a note, we did not get the IDE integration in IntelliJ IDEA to work properly.</p>
<p>Recently Buster.js was released as beta, and is worth checking out as an alternative to JsTestDriver.</p>
<h2>The framework</h2>
<p><img class="size-full wp-image-7875" src="http://open.bekk.no/wp-content/uploads/2012/01/jasmine_logo.png" alt="The Jasmine logo" width="282" height="90" align="right" /> We’ve picked out <a href="http://pivotal.github.com/jasmine/">Jasmine</a> because it is a mature (compared to most other frameworks) and a popular testing framework for JS. It features BDD syntax, which gives clear and readable tests with functionality in focus. It does not depend on any other framework and does not require a DOM. It can be run in the browser, through JsTestDriver or through node.js. It is well documented and is easy to get started with.</p>
<p>There are a few things to consider. They don’t separate between mocks, stubs and spies. All of that is packed into what Jasmine describes as a spy. The bundled matchers are good, but few. To get readable tests, it’s often necessary to write custom matchers to match the domain language. Still, we consider this one of the few viable options for doing TDD in JS.</p>
<p><a href="https://github.com/pivotal/jasmine/wiki">Installing, setting up and using Jasmine</a> is easy, and will not be detailed here. We’re using Jasmine through JsTestDriver, and have configured it thereafter.</p>
<p>QUnit was considered as an option, but it’s syntax did not help us achieve as readable and clear tests as Jasmine. It’s simplicity makes it very attractive and useful for beginners, but more advanced users will want more.</p>
<h2>Demo application</h2>
<p>As stated in the introduction, we’ll make a little application that does an “I feel lucky” search from Flickr. One of the choices we made was to have a minimal setup. No jQuery and third-party libraries in the production code, with the intention to reduce complexity and make the example more transparent as to how things work.</p>
<h3>Pre-requisites</h3>
<p>If you want to use the same setup as us, we recommend doing the following.<br />
(Or you can check out the entire project from GitHub @ <a href="http://github.com/bekk/jstdd">http://github.com/bekk/jstdd</a>).</p>
<h3>Download these libraries:</h3>
<ul>
<li><a href="https://github.com/ibolmo/jasmine-jstd-adapter">https://github.com/ibolmo/jasmine-jstd-adapter</a> (version 1.1.1)</li>
<li><a href="https://github.com/pivotal/jasmine">https://github.com/pivotal/jasmine</a> (version 1.0.1)</li>
<li><a href="http://code.google.com/p/js-test-driver/">http://code.google.com/p/js-test-driver/</a> (version 1.3.2)</li>
</ul>
<p>Create the following folder structure:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.
├── lib<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #666666; font-style: italic;"># 3rd party libs lies here</span>
│   ├── jasmine.js
│   ├── jasmine-jstd-adapter<span style="color: #000000; font-weight: bold;">/</span>
│   └── JsTestDriver-1.3.2.jar
├── spec<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #666666; font-style: italic;"># test/specs lies here</span>
├── src<span style="color: #000000; font-weight: bold;">/</span>  <span style="color: #666666; font-style: italic;"># application source lies here</span>
├── server.sh <span style="color: #666666; font-style: italic;"># Starts a JSTD server (symlinked)</span>
├── test.sh <span style="color: #666666; font-style: italic;"># Runs the test (symlinked)</span>
└── jsTestDriver.conf <span style="color: #666666; font-style: italic;"># JSTD configuration for our project</span></pre></div></div>

<p>server.sh and test.sh are just shortcuts to scripts bundled with js-test-driver.</p>
<p>Configure jsTestDriver.conf to match your setup.</p>
<h3>Getting familiar with the framework</h3>
<p>We started off with a simple test to get familiar with the syntax and to verify that everything is set up correctly. Consider it a warm-up exercise.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">describe<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Jasmine&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;makes testing JavaScript awesome!&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        expect<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeTruthy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3>Running it</h3>
<p>Running it the first time might seem a bit overly hard, but once you’re set up it’s easy to run the tests. Before you start the server, you need to write a little config file. Take a <a href="https://github.com/bekk/jstdd/blob/master/jsTestDriver.conf">look at ours</a> if you need an example.<br />
Starting the server can seem a bit tedious, but we found a shell-script that starts the server. All we had to do was modify the path to suit our project structure (see <a href="https://github.com/bekk/jstdd/blob/master/server.sh">server.sh</a>). Running it is just a matter of typing ./server and seconds later the server is up and running.</p>
<p>Example output from a test run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Running all tests
Chrome: Runner reset.
....
Total <span style="color: #000000;">1</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">1</span>; Fails: <span style="color: #000000;">0</span>; Errors: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Chrome 12.0.742.112 Mac OS: Run <span style="color: #000000;">4</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">1</span>; Fails: <span style="color: #000000;">0</span>; Errors <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Next task is capturing browsers. We spun up browsers on each others computers and went to http://[my address]:9876/capture and the browser became a slave. Excellent! We used Safari, Firefox and Chrome to test. Make sure to keep the browser running while testing.</p>
<div id="attachment_6928" class="wp-caption aligncenter" style="width: 310px"><a href="http://open.bekk.no/wp-content/uploads/2011/10/Screen-shot-2011-10-21-at-18.04.51.png"><img class="size-medium wp-image-6928 " src="http://open.bekk.no/wp-content/uploads/2011/10/Screen-shot-2011-10-21-at-18.04.51-300x133.png" alt="Screenshot from captured browser" width="300" height="133" /></a><p class="wp-caption-text">Captured browser</p></div>
<p>JsTestDriver supports distributed test-running, but that is not something we will explore in this blog post. Now all that is left is telling the server to ask the browsers to run the tests. With the scripts, it’s just a matter of typing ./test in the shell and the tests are run.</p>
<p>The flow for starting the first time is the following:<br />
1. Start server<br />
2. Capture browsers<br />
3. Run tests</p>
<p>After than you just type ./test each time you want to run the tests.</p>
<h3>Working on LuckyFlickr</h3>
<h4>Start with the tests</h4>
<p>We decided to start with writing tests to verify output on the result page. The simplest possible test we could think of was to test for a message when no result was found.</p>
<p>Next, we added a new test to verify that if a result were received, the parser would pick the first result and display the image on the result page. Since we were doing unit testing we didn’t want to go all the way to Flickr when we ran the test, so we created a <a href="https://github.com/bekk/jstdd/blob/master/spec/result-stub.js">simple stub</a> that returned some JSON data on the expected flickr format so we could run the test in isolation. The specs for the parser read:</p>
<ul>
<li>&#8220;outputting result&#8221;</li>
<ul>
<li>&#8220;should not output an image when there are no results&#8221;</li>
<li>&#8220;should output the image from the result&#8221;</li>
</ul>
</ul>
<p dir="ltr">Note: When reading these specs, read them like “Outputting result should not output an image when there are no results”.</p>
<p>When pondering what to do next, we figured we could create a test for the component that would fetch data from flickr. Since we wanted to get out data from another site, we decided to use JSONP to overcome the cross-site problem. We also wanted the component to send the flickr request asynchronously, so we had to write a test that would handle that. To fix this we created setup code to temporarily replace the default XMLHttpRequest implementation in JS with our own. That way we could control what the response would be. We decided to let it respond with the same JSON stub as in the parser test.</p>
<ul>
<li>“when querying flickr”</li>
<ul>
<li>&#8220;should create a global function that handles the JSON-P callback&#8221;</li>
<li>“should do a search and call the callback function”</li>
</ul>
</ul>
<p>The last step was to create some tests to make sure the GUI was displaying the result in the right container in the result page. On this step, we saw that some of the components came together, and introduced the need for mocking. We mocked the result given by the “fetcher”. Doing so, we’re not dependent on a connection to flickr.com. We created 2 tests for this. The first asserts that the result from flickr is displayed in the result container, and the second one asserts that “Loading” is displayed while it is fetching data from flickr.</p>
<h4>The result</h4>
<p>Since our focus was unit testing, our implementation ended out with three separate “units” that each did one important thing. We have a “fetcher” that goes out and fetches the result from Flickr, a “result parser” that knows how to parse the JSON data structure from Flickr and finally the component that enables the user to do a search. No enterprisy patterns, no unneeded complexity, no silver bullets. Just enough to make things work. Also, the design emerged from writing the tests first.</p>
<h2>Our experiences</h2>
<p>We experienced a couple of notable challenges when doing TDD in JS. Doing TDD in it self is not a problem. Some challenges appear when doing browser-specific things with JS. Such as asynchronous callbacks, handling the DOM and the AJAX browser API.</p>
<p>The DOM is an issue. When not using jQuery, there are a lot of quirks that can mess up tests in specific browsers. Also, doing DOM-operations without jQuery results in a lot of ugly code that affects readability.</p>
<p>Testing AJAX without support from the test framework is problematic, and is why several tools exist and mitigate this (Sinon.js, Mockjax, etc.). Before we changed to JSONP, we wanted to do this with no extra support, and ended up with an extremely simplified version of what the mentioned tools provide. But for most people it would be simpler to use an existing tool to help you do AJAX-testing.</p>
<p>But all these things mentioned above are relatively easy to overcome and the upside of being able to write tests for your JS code easily outweighs the small quirks you may experience. And you won’t regret spending time on writing tests when your code base is expanding and you need to make a change.</p>
<h2>Give me more!</h2>
<p><a href="http://sinonjs.org/">Sinon.JS</a> &#8211; Standalone test spies, stubs and mocks for JavaScript. Works with any unit testing framework.<br />
<a href="http://docs.jquery.com/Qunit">QUnit</a> &#8211; alternative to Jasmine. Developed by the jQuery-team<br />
<a href="https://github.com/cucumber/cucumber-js">Cucumber.JS</a> &#8211; early stages. Could be good.<br />
<a href="http://busterjs.org/">Buster.js</a> &#8211; a new test framework (currently in beta) from Christan Johansen (the man behind Sinon.js)</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/getting-started-with-js-and-tdd/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Folkevare</title>
		<link>http://open.bekk.no/folkevare/</link>
		<comments>http://open.bekk.no/folkevare/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 12:18:45 +0000</pubDate>
		<dc:creator>Holger Ludvigsen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Prosjektledelse]]></category>
		<category><![CDATA[Teknologi]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=7698</guid>
		<description><![CDATA[Har du tenkt på at utvikling handler om tre aspekter? Det er maskinvaren, det vi kan ta og føle på. Det er programvaren, et abstrakt domene. Og det er folkene som gjør det hele mulig, utviklerne, som for eksempel deg og meg.]]></description>
			<content:encoded><![CDATA[<p><strong><br />
Har du tenkt på at utvikling handler om tre aspekter? Det er maskinvaren, det vi kan ta og føle på. Det er programvaren, et abstrakt domene. Og det er folkene som gjør det hele mulig, utviklerne, som for eksempel deg og meg.</strong></p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/1.jpg"><img class="aligncenter size-full wp-image-7723" src="http://open.bekk.no/wp-content/uploads/2012/01/1.jpg" alt="" width="748" height="259" /></a></p>
<p>For 25 år siden ble det utgitt en bok Peopleware &#8211; Productive Projects and Teams. Dette er en klassiker, og jeg synes det er sunt å minnes på de prinsippene som den omhandler. I tillegg til hardware og software er det en viktig del som vi kan kalle peopleware. Det er det menneskelige aspektet ved utvikling. Det er bare én måte å få frem de systemene og løsningen som vi utvikler, og det er gjennom mennesker. Dette er smarte, høyt utdannede mennesker med en driv for teknologi.</p>
<p>Disse folkene er katalysatoren for det vi lager. Hvordan oppnår vi da de beste resultatene? Svaret er ikke kynisk eller maskinelt. Peopleware er fortsatt utrolig relevant, og det er ikke til å kimse av etter hele 25 år. Årsaken er at folk fortsatt er folk. De har de samme behovene, motivasjonene og relasjonene. Det er lett å fokusere på hvor raskt vår bransje utvikler seg teknologisk. Men folkene bak, de som gjør det hele mulig, de som skaper selve verdien. De er like menneskelige som før.</p>
<p>Det er en utbredt illusjon i databransjen, at det vi jobber med er high tech. Vi jobber med avanserte, kompliserte tekniske systemer. Det er teknologi på sitt ypperste. Datamaskiner er noe av det mest imponerende og kraftige mennesker har utviklet. Og nøkkelen til å lykkes er å forstå og benytte den mest avanserte, den høyeste, teknologien. Når de teknologiske grensene pushes går vår verden fremover, og fremskritt og konkurransefortrinn blir mulig.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/2.jpg"><img class="aligncenter size-full wp-image-7724" src="http://open.bekk.no/wp-content/uploads/2012/01/2.jpg" alt="" width="748" height="259" /></a></p>
<h2>Mennesker vs. teknologi</h2>
<p>Men tilfellet er at databransjen ikke er high tech. Dette er ikke rakettforskning. De fleste systemer har ikke behov for eller berører avansert datavitenskap eller teknologi. Mange prosjekter er avarter av create, read, update og delete, eller handler om å vise data som allerede finnes på en ny måte til brukeren. Det er som oftest ingen fysikk eller matematikk bak systemene vi lager. Selv om hardwaren er avansert og datamaskinen fundamentalt kompleks, så kan vi ikke lure oss selv til å tro at vi er i high-tech-bransjen. Det er fristende å tenke slik. At å løse de tekniske, teoretiske problemene er nøkkelen til suksess. Det er på en måte en &#8220;enkel&#8221; løsning. Det er mer håndterbart å finne den optimale algoritmen enn å forstå hvorfor Arne ikke jobber produktivt. Men suksessfulle prosjekter og effektive team handler ikke om teknologi. Det handler ofte om menneskene bak. Vår bransje er teknisk, men det er ikke teknologien som skaper suksess. Om det bare hadde vært så enkelt.</p>
<p>Har du noen gang vært på et dream team? Fått følelsen av at dere sammen jobber nær optimalt og har høy produktivitet? Har du noen gang jobbet i det motsatte? En samling mennesker som ikke får utrettet store ting. Et team på papiret, men ikke i praksis? Resultatetene fra et dream team er ikke basert på teknologien de bruker, men heller av dynamikken mellom menneskene i teamet. De utfyller hverandre. De kommuniserer godt. De vet hvor de har hverandre, og hvordan de kan bruke hverandre. Teamet er støpt. De har høy suksess med sine prosjekter, og grunnen er at de kan bruke all innsats på å løse prosjektets problemer og klientens behov, i stedet for andre ikke-verdiskapende utfordringer.</p>
<p>Hva kjennetegner et slikt team? Et tegn er at de er kvalitetsorienterte. De vet hvilke kvalitative ting som gjør prosjektet vellykket, og de fokuserer på dem. Kvalitet i datasystemer ses ofte på som en kostnad, og noe man oppnår ved å ofre andre ting, som for eksempel penger og tid. Men the dream team oppnår suksess med kvalitet som en drivfaktor. Kvaliteten gir to verdier: Man unngår bortkastet tid på å &#8220;rydde opp&#8221; om man gjør det ordentlig fra første stund. Og kvalitet er en motivasjonsfaktor i seg selv.</p>
<p>I stedet for å &#8220;cut the corners&#8221; vil the dream team gjøre det ordentlig. Det man oppnår med dette er en jevn fremgang uten skitne overraskelser som for eksempel at man ikke har noen enhetstester, eller at man har hardkodete verdier som senere ønskes å endres. Progresjonen blir kanskje lavere enn et forhastet team, men den er forutsigbar uten teknisk gjeld og andre overraskelser.</p>
<p>Jeg ble engang forsøkt rekruttert av et større IT-selskap. Jeg spurte dem rett ut: Hvorfor bør jeg jobbe hos dere? Svaret deres var: Fordi vi er den beste aktøren i markedet og har de mest fornøyde kundene. Vi er de beste og mest suksessfulle. Rekruttererne tenkte nok at dette var imponerende, men jeg tenkte &#8220;what&#8217;s in it for me?&#8221;. Folk har lyst til å realisere seg seg selv, og sine behov. Ikke bedriftens behov og finansielle målsetninger. Heldigvis finnes det en synergi her. Ved å oppfylle arbeidernes behov, kan bedriftens mål nås. Kvalitet er en motivasjon og drivkraft i seg selv. Forteller du et team at kvaliteten i det de gjør ikke er så viktig, så vil selvrespekten og moralen følge derhen. Mennesker har en iboende kraft til å realisere seg selv, å lage ting som er så bra som de har kraft til å få til.</p>
<p>Et slikt støpt team utvikler elitiske holdninger. Det er et godt tegn. De er stolte av seg selv, og har tro i sine evner. Slike team vil også tendere mot å være selvledende. Siden motivasjonen er høy, og de ønsker å nå organisasjonens mål vil de selv ta grep for å få dette til. Fra et manager-perspektiv er dette en drømmesituasjon; og bør være et mål i seg selv.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/3.jpg"><img class="aligncenter size-full wp-image-7725" src="http://open.bekk.no/wp-content/uploads/2012/01/3.jpg" alt="" width="748" height="260" /></a></p>
<h2>Miljø</h2>
<p>Mennesker er i høy grad et produkt av omgivelsene rundt en. Disse omgivelsene kan løfte en frem og få det beste ut av en, eller de kan stikke kjepper i hjulene. Har du noen gang jobbet på kontoret sent på kvelden eller i helgen? Kontorlandskapet er tomt, det er stille og øde. Der sitter du, på din sedvanlige plass. Har du lagt merke til at man ofte er høyst effektiv i dette miljøet? Man har kanskje satt av en liste med oppgaver man må få ferdig. Det ble ikke plass til dem i den vanlige arbeidstiden, så man setter opp en økt på kvelden eller i helgen. Man pløyer gjennom de oppgavene. Man går hjem med følelsen av at i dag var jeg effektiv. God progresjon i dag, godt jeg tok meg tid til den ekstra økten.</p>
<p>En viktig årsak er nok rett og slett at du fikk være i fred. Det er en tendens for åpne kontorlandskap i vår bransje. Fra åtte om morgenen til fire om ettermiddagen er det folk rundt deg. Disse folkene skaper støy, uro og avbrytelser. På grunn av den innebygde forsinkelsen vårt sinn tar for å komme ordentlig i gang med en mental oppgave kan disse forstyrrelsene hindre produktiviteten. Vi jobber i en kunnskapsbransje, og tankekraft er essensen i produktene vi skaper. God konsentrasjon er avgjørende, men til dels ikke mulig i et støyende og kollektivt kontorlandskap. Det er en kontradiksjon egentlig; vi har høy utdannelse, jobber med kompliserte abstrakte konsepter som ikke har noen fysisk manifestasjon. Men allikevel er en lukkbar kontordør en luksus bedriften ikke tar seg råd til.</p>
<p>I Peopleware foretok de en programmeringsøvelse hvor et spesifisert system skulle implementeres. De gruppene som gjorde det godt ble sammenlignet med de som ikke nådde milepælene på samme tid:</p>
<table>
<tbody>
<tr>
<td></td>
<td>Den beste fjerdedelen</td>
<td>Den svakeste fjerdedelen</td>
</tr>
<tr>
<td>Hva er ditt eget arbeidsområde?</td>
<td>7 m2</td>
<td>4 m2</td>
</tr>
<tr>
<td>Er arbeidsområde stille?</td>
<td>57 % ja</td>
<td>29 % ja</td>
</tr>
<tr>
<td>Er arbeidsområdet privat?</td>
<td>62 % ja</td>
<td>19 % ja</td>
</tr>
</tbody>
</table>
<p>Resultatene er kanskje ikke overraskende. De som gjorde det best hadde avlukkede kontorer som de delte med 0, 1 eller 2 andre. De svakeste jobbet i åpne områder. Mange kan nok si seg enige i at kollektive rom hemmer konsentrasjonen. Men har du kvantifisert hvor mye plassbesparelsene koster i produktivitet?</p>
<h2>Management</h2>
<p>Hva er jobben til en manager? Han driver ikke direkte med verdiskapningen. Det er det utviklerne som gjør. Det er de som løser kunden og brukernes problemer. En av managerens viktigste oppgaver er å få de under ham til å gjøre en god jobb. Den beste jobben gitt deres forutsetninger. Det finnes mange ulike synspunkter på hvordan man får dette til. En viktig management-oppgave er å sette deadlines. Slike frister kan brukes som et virkemiddel i seg selv. Parkinsons &#8220;lov&#8221; sier at arbeid utvider seg selv til å fylle tiden det er satt av til. Vi kjenner alle godt til rasjonalen bak. Om man har press på seg skynder man seg. Om noe ikke haster kan man ta seg bedre tid. Dette leder til en logikk som er mye brukt i management. Tighte, kanskje urealistiske deadlines virker motiverende og øker produktiviteten. Bare pass på å ikke avslør at deadlinen er kunstig tidlig!</p>
<p>I praksis fungerer det ikke. Utviklerens produktivitet og arbeidsmetode er avhengig av deadlines, men en urealistisk deadline kan være høyst demoraliserende. En undersøkelse ble foretatt blant flere titalls prosjekter. Det ble sett på hvem som utførte tidsestimatetene, og hvor høy produktiviteten var for hver oppgave. Hvor utvikleren gjorde estimatet var produktiviteten 8. Dette er så klart et relativt tall. Hvor utviklerens sjef gjorde estimatet var produktiviteten 6.6. Haha, tenker man så klart. Dumme manageren tror han vet bedre enn gutta på gulvet!</p>
<p>Men i tilfeller hvor en ekstern system-analytiker gjorde estimeringen var produktiveten enda høyere med 9.5. Hva er grunnen til dette? Det kan være at systemanalytikeren er en profesjonell estimerer med god erfaring fra tilsvarende implementasjoner. At hans estimater er nærmere det egentlige innsatsbehovet kan være motiverende i seg selv. Realistiske deadlines er gir dermed høyst produktivitet. Et interessant resultat oppsto i oppgaver hvor intet estimat i det hele tatt var gitt. Her var produktiviteten 12, og dermed høyest. Dette kontradikterer helt tydelig Parkinsons lov, og setter i tvil dens effektivetet som management-verktøy.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/4.jpg"><img class="aligncenter size-full wp-image-7726" src="http://open.bekk.no/wp-content/uploads/2012/01/4.jpg" alt="" width="748" height="260" /></a></p>
<h2>Dream manager</h2>
<p>Et dream team krever en dream manager. Men hva kjennetegner en slik manager? Det er kanskje ikke hva en tradisjonelt forbinder med ledelse. Et dream team har en iboende egenskap å gjøre det godt, og en dream manager <em>enabler</em> dette. Det er ikke så lett å måle en managers evne til å enable sitt team, men det er allikevel en av det viktigste egenskapene. Det motsatte ville vært defensivt management. En defensiv manager stoler ikke på sine &#8220;undersåtter&#8221;. Han er opptatt av sitt eget bilde, og forsvarer det mot eventuelle utfordringer. Han ser på seg selv om drivkraften bak teamets progresjon og suksess, og underminerer deres evne til fatte de riktige avgjørelsene selv.</p>
<p>Et godt motivert og fungerende team er en drivkraft i seg selv. En god manager vil utnytte disse kreftene og enable og løfte teamet. Hindre i veien elimineres, og byråkratiske eller organisatoriske problemer løses. Manageren er oljen i teamets maskineri. Disse egenskapene er ikke alltid like lette å observere på overflaten. Kanskje manageren virker overflødig på grunn av teamets selvstendighet og effektivitet. Men nettopp dette kan være resultatet av en managers dedikerte arbeid bak kulissene.</p>
<h2>Folkevare</h2>
<p>Data og systemutvikling er tilsynelatende en teknologisk, komputasjonell bransje. Men faktum er at det er menneskene som jobber med dette som er drivkraften. De teknologiske utfordringene er interessante og nyttige som et minstemål. Men løsningene bunner alltid ut i mennesker som jobber sammen. Mennesker med sine behov, sine mål og sine motivasjoner. Disse endrer seg ikke i samme takt som prosessorkraft og minnestørrelse.</p>
<p>Det er ikke like lett å analysere sosiologien bak utvikling som det er å drøfte teknologien, men x-faktoren i systemutvikling er menneskene bak. Mens maskinvare og programvare skyter fremover, er det fortsatt de samme type mennesker som jobber med disse tingene. Kun ved å forstå disse temaene kan man få det meste ut av teknologien og lykkes i sine prosjekter.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/folkevare/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hva er kvalitet?</title>
		<link>http://open.bekk.no/hva-er-kvalitet/</link>
		<comments>http://open.bekk.no/hva-er-kvalitet/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 15:23:18 +0000</pubDate>
		<dc:creator>Vegard Hartmann</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[craftsmanship]]></category>
		<category><![CDATA[håndverk]]></category>
		<category><![CDATA[kvalitet]]></category>
		<category><![CDATA[smidig]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=7268</guid>
		<description><![CDATA[I faggruppen Kvalitet og testing har vi gjennom 4 år diskutert kvalitetsrelaterte temaer. Vi har blant annet vært innom teknikker som TDD og BDD, ulike smidige metoder som Scrum og Kanban, verktøy for testing og kvalitetsheving samt kulturbygging og craftsmanship. Konklusjonen er at kvalitet kan være så mangt. Selv i faggruppen har vi fortsatt hvert [...]]]></description>
			<content:encoded><![CDATA[<p>I faggruppen <em>Kvalitet og testing</em> har vi gjennom 4 år diskutert kvalitetsrelaterte temaer. Vi har blant annet vært innom teknikker som TDD og BDD, ulike smidige metoder som Scrum og Kanban, verktøy for testing og kvalitetsheving samt kulturbygging og craftsmanship.</p>
<p>Konklusjonen er at kvalitet kan være så mangt. Selv i faggruppen har vi fortsatt hvert vårt syn på hva kvalitet er.</p>
<p><em>Her er våre tanker: hva er dine?</em></p>
<p style="text-align: center;"><a href="http://open.bekk.no/wp-content/uploads/2011/11/Kvalitet.png"><img class="aligncenter size-full wp-image-7321" title="Kvalitet" src="http://open.bekk.no/wp-content/uploads/2011/11/Kvalitet.png" alt="Kvalitet tag cloud" width="670" height="281" /></a></p>
<p><span id="more-7268"></span></p>
<h4>Vegard Hartmann</h4>
<p><img class="size-thumbnail wp-image-7271 alignright" style="margin: 0 0 8px 20px" title="Vegard" src="http://open.bekk.no/wp-content/uploads/2011/11/vegard.jpg" alt="" width="150" align="right" /></p>
<p>Kvalitet er for mange et subjektivt begrep og kan derfor være vanskelig å sette ord på. Når jeg tenker på noe som har kvalitet så tenker jeg på noe som er solid, robust og som varer lenge.</p>
<p>Dette passer imidlertid kanskje ikke like godt for software. Der kan det hende at egenskaper som stabilitet, funksjonalitet og fleksibilitet er mer dekkende for å beskrive kvalitet.</p>
<p>Kvalitet dreier seg om egenskaper, ISO 9000 definerer kvalitet som &#8220;Degree to which a set of inherent characteristics fulfills requirements&#8221;. Requirements, eller krav, er i denne sammenhengen behov eller forventninger man har til løsningen.</p>
<p>Men hvilke behov og forventninger har man egentlig til løsningen? Og vil ikke disse variere fra person til person? Jeg synes Gerald Weinberg har satt ord på en veldig fin definisjon av kvalitet: &#8220;Quality is value to some person.&#8221; Dette er en enkel definisjon som er lett å huske.</p>
<p><em>For å levere kvalitet må man finne ut av hvem som er interessenter i løsningen det er snakk om og hva som gir verdi for disse personene.</em></p>
<h4>Børge Bardo</h4>
<p><img class="alignleft size-thumbnail wp-image-7275" style="margin: 0 20px 8px 0" title="Børge" src="http://open.bekk.no/wp-content/uploads/2011/11/borge.jpg" alt="" width="150" align="left" /></p>
<p>Kvalitet for meg er at systemet oppfyller det kravene sier og samtidig gir en merverdi for kunden. Systemet må kunne brukes på en effektiv og hensiktsmessig måte av brukere. Det oppfyller ikke-funksjonelle krav som er viktig for forretningen slik at systemets funksjonalitet er tilgjengelig når det skal.</p>
<p>Systemet er lett å endre og utvide med ny funksjonalitet i takt med endrede og nye krav. Er lett å skrive tester og har allerede tester som beskriver systemets oppførsel. Det er skrevet på en måte som gjør at det er lett å sette seg inn og at jeg blir i godt humør når jeg leser koden.</p>
<h4>Øyvind Kvangardsnes</h4>
<p><img class="alignright size-thumbnail wp-image-7276" style="margin: 0 0 8px 20px" title="Øyvind" src="http://open.bekk.no/wp-content/uploads/2011/11/oyvind.jpg" alt="" width="150" align="right" /></p>
<p>Kvalitet! Alle vet hva det er, men vi har stooore problemer med å forklare hva det faktisk betyr. Det er jo fordi uttrykket ikke på noen måte er entydig.</p>
<p>I mitt hode er kvalitet den gode følelsen man får når noe bare funker. &#8220;Noe&#8221; og &#8220;funker&#8221; er operative ord; betydningen avhenger 100% av hvem man er og hva man snakker om.</p>
<p>Når vi lager programvare, så er det mange som bryr seg om kvaliteten.<br />
Hva de bryr seg om varierer; stikkord kan være brukervennlighet, responstid, kodelinjer, time-to-market, internpolitikk, driftbarhet, ressursbruk, logging osv.</p>
<p>De bryr seg om hva, eller hvordan, eller hvorfor.</p>
<p>Jeg vil levere kvalitet! Når de som bryr seg sier <em>&#8220;det funker bra&#8221;</em>, så vet jeg at jeg er på sporet <img src='http://open.bekk.no/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h4>Torstein Nicolaysen</h4>
<p><img class="alignleft size-full wp-image-7329" style="margin: 0 20px 8px 0" title="Torstein" src="http://open.bekk.no/wp-content/uploads/2011/11/Torstein_BEKK.jpg" alt="" width="150" align="left" /></p>
<p><em>Kvalitet er en følelse og opplevelse.</em><br />
Du vet ikke nødvendigvis om den er der, men du merker om den mangler. Det er noe som er lett å kjenne igjen, men vanskelig å definere. </p>
<p>Kvalitet er vanskelig å skape, og kan kun skapes gjennom fokusert og dedikert arbeid av noen som er bevisst, kunnskapsrik og lidenskapelig opptatt av håndverket sitt. </p>
<p>Resultatet er noe som fungerer slik det skal – og ofte litt bedre. Det er prikken over i-en som vi forventer skal være der. </p>
<p>Det er det som gjør jobben morsom. Det er det som gjør kunden fornøyd. Kvalitet er det vi leverer når vi presterer som best!</p>
<h4>Bent Kristiansen</h4>
<p><img class="alignright size-thumbnail wp-image-7285" style="margin: 0 0 8px 20px" title="Bent" src="http://open.bekk.no/wp-content/uploads/2011/11/bent.jpg" alt="" width="150" align="right" /></p>
<p>Kapasitet, ytelse, brukervennlighet, stabilitet og tilgjengelighet er viktige kvalitetsfaktorer.</p>
<p>Kvalitet er avhengig av &#8220;interessehaver&#8221;. IT-systemer har ofte mange interessehavere/kravstillere, som igjen har forskjellige kriterier for hva de opplever som kvalitet. For sluttbruker er kvalitet Look and feel, respons og at de finner enkelt fram. For driftsansvarlige er kvalitet blant annet gode systemlogger med korrekte loggnivå, slik at det umiddelbart kan tas tak i eventuelle kritiske feil som oppstår.</p>
<p>Kvalitet er tidsavhengig. Endringer i funksjonsbehov og infrastruktur, samt trender gjør at system kan bli utdatert på kort tid. At systemet er godt dokumentert gjennom funksjonelle tester og enhetstester gjør at det er fleksibelt i forhold til videreutvikling.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/hva-er-kvalitet/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Devops og andre moteord</title>
		<link>http://open.bekk.no/devops-og-andre-moteord/</link>
		<comments>http://open.bekk.no/devops-og-andre-moteord/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 09:07:15 +0000</pubDate>
		<dc:creator>Frode Reinertsen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Drift]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=7146</guid>
		<description><![CDATA[Med tid til annen dukker det opp ord som lyder godt i teknologiprat, uten at folk har en samstemt oppfatning av hva de betyr. Devops er et av dem. Opprinnelsen til uttrykket stammer fra Patrick Debois og konferansen Devops days. Patrick Debois lener seg på et blogginnlegg for utdyping av begrepet. Essensen i dette ligger [...]]]></description>
			<content:encoded><![CDATA[<p>Med tid til annen dukker det opp ord som lyder godt i teknologiprat, uten at folk har en samstemt oppfatning av hva de betyr. Devops er et av dem. <a title="Podcast som tar opp opprinnelsen til devops" href="http://devopscafe.org/show/2010/9/15/episode-12.html" target="_blank">Opprinnelsen til uttrykket</a> stammer fra Patrick Debois og konferansen <a title="Konferansen Devops days" href="http://devopsdays.org/" target="_blank">Devops days</a>. Patrick Debois lener seg på <a title="What is this devops thing anyway" href="http://www.jedi.be/blog/2010/02/12/what-is-this-devops-thing-anyway/" target="_blank">et blogginnlegg</a> for utdyping av begrepet. Essensen i dette ligger i oppsummeringen:</p>
<blockquote><p>I&#8217;m convinced this isn&#8217;t just a fad, and we&#8217;re on the brink of a revolution in the software industry &#8211; a paradigm shift in which developers and sysadmins start to work together, to train each other, and ultimately to blur the boundary &#8211; welcome to the world of the Devop.</p></blockquote>
<p>Så vi snakker også om en Devop, som en rolle? Gjerne for meg, men da som tillegg til et begrep som handler om det å få kontroll over og kvalitet på utrulling og drift. Det er ihvertfall det jeg ønsker å legge i det.</p>
<p>Det hadde gjort seg med en norsk oversettelse. Noen forslag?</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/devops-og-andre-moteord/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Web-deploy i .Net ska inte vara så svårt!</title>
		<link>http://open.bekk.no/web-deploy-i-net-ska-inte-vara-sa-svart/</link>
		<comments>http://open.bekk.no/web-deploy-i-net-ska-inte-vara-sa-svart/#comments</comments>
		<pubDate>Sat, 22 Oct 2011 17:15:04 +0000</pubDate>
		<dc:creator>Tomas Jansson</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[drift]]></category>
		<category><![CDATA[kontinuerlige leveranser]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6961</guid>
		<description><![CDATA[Att sätta upp en byggmiljö i .Net är inte svårt, men alldeles för få personer har gjort det och dokumenterat det. Detta inlägg ska vara en guide för hur du enkelt kommer igång med kontinuerlig deployment. Så här kommer ytterligare ett inlägg inom samma ämne som de två senaste inläggen.]]></description>
			<content:encoded><![CDATA[<p>Det är säkert många av oss som varit inblandade i ett eller flera prosjekt där det varit svårt att sätta upp en ny lokal, test eller produktionsmiljö. Ofta så har det innefattat ett flertal manuella steg där man flyttar det som ska flyttas manuellt enligt ett dokument som uppdateras alldeles för sällan om man ser till hur viktigt det är. Personligen känns detta helt överflödigt och framförallt är det slöseri eller risk av:</p>
<ul>
<li>tid/resurser: man lägger tid på något som kan automatiseras</li>
<li>kompetens: om den personen försvinner som sköter deploy, vad gör man då?</li>
<li>dokumentation: den uppdateras inte ordentligt och det är svårt att förklara allt i detalj, med ett enklare dokument som beskriver en enklare process är det betydligt mer värdefullt</li>
<li>pengar: allt ovan tillsammans gör att man har en process som snarare blir en belastning än stärker organisationen.</li>
</ul>
<p>Så hur sätter man då upp en agil web-deployprocess i .Net? Resten av denna post kommer ge dig en enkel men grundläggande beskrivning hur du får till en smidig web-deployprocess i .Net med web deploy 2.0 och slutligen automatiserad med Teamcity. Den målbild vi är ute efter är följande:</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/10/ContinousIntegration.png"><img class="aligncenter size-large wp-image-6963" title="Continous integration setup" src="http://open.bekk.no/wp-content/uploads/2011/10/ContinousIntegration-1024x479.png" alt="Continous integration setup" width="750" height="479" /></a><a href="http://open.bekk.no/wp-content/uploads/2011/10/ContinousIntegration.png"><br />
</a><br />
Det är en rätt så rakt fram uppsättning. Man har utvecklare som sitter på utvecklingsdatorer som kommunicerar med den källkodsmiljö man har som t.ex. git eller TFS. Når en utvecklare pushar kod till källkodskontrollen så triggar det ett bygg på byggservern som då hämtar senaste versionen. Om bygget går bra, dvs. det bygger och de testar man har definierat går bra, så deployar byggservern till den miljö som koden var avsedd för.</p>
<p>Det är sex steg som vi kommer gå igenom för att få detta på plats:</p>
<ol>
<li>Web deploy 2.0 och IIS 7</li>
<li>Projektspecifika inställningar</li>
<li>Config-transformationer</li>
<li>Att bygga ett deploypaket</li>
<li>Deploy av ett deploypaket</li>
<li>Konfigurering av Teamcity för kontinuerlig deployment</li>
</ol>
<h4 dir="ltr">Web deploy 2.0 och IIS 7 konfigurasjon</h4>
<p>Denna post fokuserar bare på deploy till IIS 7 och som verktyg för att göra utföra deployen kommer Web deploy 2.0 (Web deployment tool) från Microsoft att användas. Detta må man göra på de servrar man vill göra en deploy till, men när det är konfigurerat så ska man inte behöva göra så mycket mer efter utom eventuellt sätta skapa en eller annan site.</p>
<p>Följande checklista är det som ska göras för Wen deploy 2.0 och IIS 7.</p>
<ul>
<li>Installera Web deploy 2.0 från <a href="http://www.iis.net/download/webdeploy">http://www.iis.net/download/webdeploy</a>.</li>
<li>Aktivera “Web Service Management” (detta gäller för Windows 2008) genom att gå till “Control Panel\All Control Panel Items\Programs and Features” och sedan “Turn Windows features on or off” för att där aktiver “IIS Management Serivce” enligt bilden nedan.</li>
</ul>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/10/IISManagementService.png"><img class="aligncenter size-full wp-image-6966" title="IIS Management Service" src="http://open.bekk.no/wp-content/uploads/2011/10/IISManagementService.png" alt="IIS Management Service activtion" width="428" height="375" /></a></p>
<ul>
<li>Starta “Management Service” (detta gäller för Windows 2008) genom i “Internet Information Services (IIS) Manager” markera den server som du vill deploya till. Där klickar du på “Management Service” under “Management”-kategorin. Inne på “Management Service” så startar du servicen och registrerar vilken port den kör på.</li>
<li>Gå sedan in på “IIS Manager Users” som också ligger under “Management”-kategorin och skapa dig en deployanvändare. Denna användare är den som kommer användas vid deploy till servern, notera att den inte behöver vara en windows- eller AD-användare.</li>
<li>För att ge våran deployanvändare rättigheter så går man in på “Management Service Delegation” under “Management”-kategorin. Där väljer man “Add rule&#8230;” templaten man ska använda är vanligtvis “Deploy Application with Content”. De inställningar jag skulle lägga till är följande:</li>
<ul>
<li>Under “Providers” skulle jag lägga till: createApp och setAcl</li>
<li>“Run As”: där skulle jag sätta en faktiskt windows- eller AD-användare som man skapat för att göra deploy till servern.</li>
</ul>
<li>I nästa steg så lägger du till den “IIS manager” som du skapade tidigare.</li>
<li>För att ge våran användare som vi skapat rättigheter att göra något med en site så måste vi lägga till den till en site. Så istället för att ha IIS severn markerad till vänster så expanderar man “sites” och väljer den site man vill deloya till. När siten är valt så går man in på “IIS Manager Permissions” och lägger till sin användaren som man skapat.</li>
</ul>
<p>Det var allt vi behöver göra för att installera Web deploy och konfigurera IIS.</p>
<h4 dir="ltr">Projektspecifika inställningar</h4>
<p>Det är inte mycket man behöver göra på projektnivå, men det är en sak som är relativt viktig och det är att definiera default värden för vart din applikation ska deployas när man väl gör det. Genom att högerklicka på din applikation i Visual Studio och välja “Properties” och sedan “Package/Publish Web” så hittar du ett fält som heter “IIS Web site/application name to use on the destination server”. Här definierar du vart du vill deploya din applikation i olika scenarior som test, stage och produktionsbygg t.ex. Helt enkelt en inställning per byggkonfiguration. Det går vid senare tillfälle definiera att man vill göra en deploy till ett annat ställe, men man bör sätta dessa så korrekt som möjligt.</p>
<h4 dir="ltr">Config-transformationer</h4>
<p>Visual Studio 2010 kommer inbyggt med stöd för att enkelt transformera Web.config för ett projekt. När du skapar att MVC projekt till exempel så skapas det med en Web.config fil samt två transformationsfiler som heter Web.Debug.config och Web.Release.config.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/10/web.config.png"><img class="aligncenter size-full wp-image-6968" title="web.config med transformationer" src="http://open.bekk.no/wp-content/uploads/2011/10/web.config.png" alt="web.config med transformationer" width="267" height="96" /></a><br />
Transformationsfilerna kommer användas när du gör en deploy med ett deploypaket, notera att transformationerna inte görs när du bygger ditt projekt. Att skapa dessa transformationsfiler är relativt enkelt och det går att läsa om de olika transformationerna du kan göra här: <a href="http://go.microsoft.com/fwlink/?LinkId=125889">http://go.microsoft.com/fwlink/?LinkId=125889</a>.</p>
<h4 dir="ltr">Att bygga ett deploypaket</h4>
<p>Det finns två sätt att bygga deployment paket på, genom Visual Studio 2010 som är en trivial uppgift och genom att använda sig av msbuild vilket är lite mer komplicerat men som vi måste lära oss om vi vill göra en deploy från en byggserver som Teamcity.</p>
<p>Att bygga ett deployment paket i Visual Studio 2010 kan inte bli enklare än det är. Du högerklickar på den webapplikation som du vill bygga och väljer “Build Deployment Package”. Visual Studio kommer då att bygga ett deploypaket åt dig för den konfiguration som är vald. När du bygger dit deploypaket så skapas en “Package”-katalog under “&lt;project dir&gt;\obj\&lt;build configuration&gt;”. “Package”-katalogen innehåller följande:</p>
<ul>
<li>PackageTmp &#8211; en temporär katalog som innehåller resultatet av bygget innan det skapas ett deploypaket av det.</li>
<li>&lt;project name&gt;.deploy.cmd &#8211; som är ett färdigt exekverbart script du kan använda dig av för att göra en deploy.</li>
<li>&lt;project name&gt;.zip &#8211; det paket som du kan installera.</li>
<li>&lt;project name&gt;.SetParameters.xml &#8211; om du har definierat parametrar för ditt paket så kan du sätta de här (går inte igenom detta i den här blogposten)</li>
<li>&lt;project name&gt;.SourceManifest.xml &#8211; definierar uppgifter som ska göras när du gör själva deployen, t.ex. sätta rättigheter (går inte igenom detta i den här blogposten)</li>
</ul>
<p>Att bygga ett deployment paket med msbuild är inte så mycket mer komplext egentligen, men den genomsnittliga .Net-utvecklaren är kanske lite rädd så fort man ska börja använda sig av en konsollapplikation så hoppas följande triviala rad visar på att det inte är så komplicerat. Så det man behöver göra för att bygga ett deploymentpaket med msbuild är att köra följande:</p>
<p>msbuild &lt;project name&gt;.csproj /T:package /P:Configuration=&lt;Configuration&gt;</p>
<p>Parametrarna som används definierar att vi vill köra en msbuild target som heter “Package” som bygger själva deploymentpaketet och sedan definierar den andra parametern vilken konfiguration vi vill använda oss av när vi bygger, t.ex. Debug eller Release. Samma typ av filer ska skapas av det kommandot och de lägger sig på samma ställe.</p>
<p>Nu när vi vet hur man bygger ett deploypaket är nästa steg att utföra själva deployen.</p>
<h4 dir="ltr">Deploy av ett deploypaket</h4>
<p>Deploy går att göra på fyra olika och enkla sätt</p>
<ul>
<li>Direkt i IIS,</li>
<li>Direkt i Visual Studio,</li>
<li>Genom att exekvera den körbara fil man fick när man byggde paketet,</li>
<li>Genom att exekvera ett msbuild kommando som bygger och gör en deployment.</li>
</ul>
<p>Att installera ett paket i IIS är trivialt. I IIS Manager så högerklickar du på den site som du vill göra din deploy till och väljer “Deploy-&gt;Import Application&#8230;”. Då får du en dialog där du ska leta upp den zip-fil som skapades när du byggde ditt deploymentpaket. Sen ska det bara vara att klicka next och finish. Detta sätt att deploya på är bra om man eventuellt inte har direkt tillgång till servern som man ska göra deploy till, då kan man bara leverera det som ska deployas till en som har rättigheter så gör han uppgiften.</p>
<p>Att göra en deploy från Visual Studio är i stort sett lika enkelt som att göra det direkt i IIS. I Visual Studio så högerklickar du på det webprojekt som du vill göra en deploy av och väljer “Publish&#8230;”. Här ska du fylla i de uppgifterna vi satte upp i IIS, dvs. service URL, vart vi ska göra våran deployment och den IIS användare som vi definierade IIS. Du kanske behöver kryssa för “Allow untrusted certificate” och antagligen så vill du kryssa för “Mark as IIS application on destination”.</p>
<p>Att använda sig av den exekverbara filen man fick när man byggde sitt deployment paket är ett enkelt sätt att göra en deployment på. Om du befinner dig på servern och har kopierat allt i den “Package”-katalog som skapades så är det enda du behöver köra om du står i “Package”-katalogen följande:</p>
<p><code>&lt;Project name&gt;.deploy.cmd /y</code></p>
<p>Så mycket enklare än det kan det inte bli, men tyvärr är vi inte klara. Om vi skulle vilja göra en deploy till en annan server behöver vi ange lite mer information så då ser vårat kommando ut ungefär så här:</p>
<p><code>&lt;Project name&gt;.deploy.cmd /y "/M:&lt;Deploy server&gt;?site=&lt;site name&gt;"<br />
/u:&lt;IIS user&gt;<br />
/p:&lt;IIS user password&gt;<br />
-allowUntrusted /A:basic</code></p>
<p>Notera att det är citat-tecken runt server- och siteparametrarna, detta är för att annars så splittas parametern upp på “=”. När detta brukas i Teamcity så behöver man ha dubbla citat-tecken av någon anledning. En sak till är att om man försöker göra en deploy till en site som inte är default i applikationen så behöver man eventuellt gå in och ändra till rätt site i filen &lt;project name&gt;.SetParameters.xml.</p>
<p>Men för att göra det ännu enklare på våran byggserver så ska vi istället använda oss av msbuild för att göra deploy, vilket gör att vi kommer göra både bygg av deploypaket i samma steg. Det msbuild kommando man behöver är följande</p>
<p><code>msbuild &lt;project name&gt;.csproj /P:Configuration=&lt;configuration&gt;<br />
/P:DeployOnBuild=True<br />
/P:DeployTarget=MSDeployPublish<br />
"/P:MsDeployServiceUrl=&lt;your deploy service&gt;?site=&lt;your site&gt;"<br />
/P:AllowUntrustedCertificate=true<br />
/P:MSDeployPublishMethod=WMSvc<br />
/P:CreatePackageOnPublish=True<br />
/P:UserName=&lt;your IIS user&gt;<br />
/P:Password=&lt;your IIS user password&gt;</code></p>
<p>Det är många parametrar men alla är väldigt tydliga med vad de gör. Att vi har allt i ett kommando gör nu när vi ska konfigurera upp Teamcity att vi får ett byggsteg mindre än om vi haft det i två olika delar.</p>
<p>Så då när vi nu har definierat det kommando som vi behöver för att göra en automatisk deploy från Teamcity är det dags för det sista steget.</p>
<h4 dir="ltr">Konfigurering av Teamcity</h4>
<p>Jag kommer enbart fokusera på hur man gör deploy från Teamcity, jag räknar med att läsaren redan vet hur man triggar ett bygg på check-in av kod eller liknande.</p>
<p>Det första vi gör är att definiera ett antal byggparametrar enligt figuren nedan.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/10/BuildParameters.png"><img class="aligncenter size-large wp-image-6969" title="Build Parameters i Teamcity" src="http://open.bekk.no/wp-content/uploads/2011/10/BuildParameters-1024x297.png" alt="Build Parameters i Teamcity" width="750" height="297" /></a><br />
Som du ser är detta parametrarna som användes i sista exemplet på hur man gör en deploy. Det underlättar om du definierar de som system parametrar då msbuild scripten i byggkonfigurationen använder sig av de parametrarna automatiskt. Det tar oss till nästa steg, när du har definierat alla de byggparametrarna så skapar du ett bygg steg inställningarna enligt bilden nedan om du använder .NET 4.0. Givetvis så är det bra om du anger ett namn på konfiguration och sökvägen till den csproj-filen för den webapplikation som du ska bygga.</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/10/BuildConfiguration.png"><img class="aligncenter size-full wp-image-6970" title="Build Configuration" src="http://open.bekk.no/wp-content/uploads/2011/10/BuildConfiguration.png" alt="Build configuration for Teamcity" width="750" height="619" /></a></p>
<p>Ett sista steg om du vill enkelt ska kunna ladda ner det deploypaket som skapades är att lägga till en artifakt under “General Settings”. Sökvägen man ska lägga till är den till din “Package”-katalog, vilket borde vara något i stil med:</p>
<p><code>&lt;Path to project&gt;\obj\%build.configuration%\Package</code></p>
<p>“Path to project” är den sökväg som du har till projektet när byggservern har checkat ut koden.</p>
<p>Att vi har allt i parametrar gör det väldigt enkelt att skapa en ny konfiguration för att göra en deploy till en annan server eller site, allt du behöver göra är att kopiera konfigurationen och sedan ändra de parametrar som behöver ändras.</p>
<h4 dir="ltr">Avslutning</h4>
<p>Det var alla steg som man behöver göra för att få upp en relativt automatiserad process för att deploya dina webprojekt. Web deploy 2.0 har mycket mer funktionalitet än det som gåtts igenom i denna blogpost, men detta borde få dig att komma igång med automatiseringsprocessen. Om du vill lära dig mer om hur du till exempel sätter rättigheter på kataloger eller ändrar värden i registret så rekommenderar jag följande två blogginlägg:</p>
<p>Modifying directory permissions with Web Deployment &#8211; <a href="http://leethams.wordpress.com/2010/06/12/modifying-directory-permissions-with-web-deployment/">http://leethams.wordpress.com/2010/06/12/modifying-directory-permissions-with-web-deployment/</a><br />
How to extend target file to include registry settings for web project package &#8211; <a href="http://blogs.msdn.com/b/webdevtools/archive/2010/02/09/how-to-extend-target-file-to-include-registry-settings-for-web-project-package.aspx">http://blogs.msdn.com/b/webdevtools/archive/2010/02/09/how-to-extend-target-file-to-include-registry-settings-for-web-project-package.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/web-deploy-i-net-ska-inte-vara-sa-svart/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Felles ansvar for produksjon!</title>
		<link>http://open.bekk.no/felles-ansvar-for-produksjon/</link>
		<comments>http://open.bekk.no/felles-ansvar-for-produksjon/#comments</comments>
		<pubDate>Fri, 21 Oct 2011 19:18:32 +0000</pubDate>
		<dc:creator>Ole Christian Rynning</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[drift]]></category>
		<category><![CDATA[kontinuerlige leveranser]]></category>
		<category><![CDATA[kvalitet]]></category>
		<category><![CDATA[produksjon]]></category>
		<category><![CDATA[utvikling]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6893</guid>
		<description><![CDATA[Jeg skulle egentlig bare kommentere på Torstein sin blogpost i går: <a href="http://open.bekk.no/slipp-utvikleren-til/">Slipp utvikleren til!</a>. Svaret ble litt langt, så fant ut jeg kunne like så godt lage en oppfølger.

Min generelle oppfatning er at løsninger blir stort sett bedre, hverdagen enklere for både drift og programmerer, og applikasjonene mer driftbare når også programmerere har ansvar for produksjon. ]]></description>
			<content:encoded><![CDATA[<p>Jeg skulle egentlig bare kommentere på Torstein sin blogpost igår: <a href="http://open.bekk.no/slipp-utvikleren-til/">Slipp utvikleren til!</a>. Svaret ble litt langt, så fant ut jeg kunne like så godt lage en oppfølger.</p>
<p>Min generelle oppfatning er at løsninger blir stort sett bedre, hverdagen enklere for både drift og programmerer, og applikasjonene mer driftbare når også programmerere har ansvar for produksjon. </p>
<p>Erfaringen min peker på at ingen tilgang bidrar til:</p>
<h4>1. Manglende fokus på driftbarhet og automatisering</h4>
<p>Ansvarsfølelsen for produksjon blir lav til forsvinnende blant oss programmerere. Jeg har hørt utviklere oppriktig si &#8220;jeg er ferdig når det er i QA, PROD er ikke mitt ansvar&#8221;. Om det kommer massive ytelsesproblemer og bugs i produksjon &#8211; hvor koden faktisk brukes &#8211; betyr det ikke så mye. Jeg har sett logger i applikasjoner bli dårlige til ubrukelige. Alt eller ingenting logges. Det lages heller ingen monitorerings- eller diagnoseverktøy (f.eks. fordi vi ikke får tilgang til å bruke dem uansett). Og utrulling forblir basert på manuelle rutiner.</p>
<h4>2. Færre releaser og lengre tid til markedet</h4>
<p>Når det er så tungt og vanskelig å utføre prodsetting, så er det lettere å utsette releasene. Dette fører igjen til enda større kompleksitet og risiko for feil. Det inntreffer gjerne astronomiske problemer når det først releases. Drift igjen får en aversjon mot releaser, og optimaliserer for å slippe dem.</p>
<h4>3. Økt responstid for feilretting (bugs)</h4>
<p>Økt kommunikasjonsoverhead betyr at det tar lengre tid å finne ut hva som skjer&#8230; Samarbeidet blir tyngre og iblant må vi tilogmed (både drift og utvikling) streve for at det ikke skal surne helt til. Utviklere blir masekoppene, som tror de vet bedre; drift blir de som ikke svarer, ikke bryr seg, osv.</p>
<h4>= Mindre forretningsverdi</h4>
<p>Dette oversetter ganske direkte til dårligere kvalitet*, tapte muligheter og tapte inntekter/økte kostnader. (* lavere kvalitet betyr økte kostnader, tap av brand value, osv.) </p>
<p>Jeg tror verken systemadministratorer eller programmerere er særlig interesserte i å ha det slik. Vi vil heller ha bra og enkle systemer å drifte, levere ny forretningsverdi og gjøre kunder og brukere fornøyde, og ha et bra samarbeid.</p>
<p>OK. Det finnes alltid et unntak her og der. Noen systemer har blitt lappet sammen med tape, plaster, sysaker og endel kreativ tenking (fra både utvikling og drift). Disse klapper gjerne sammen om en leser av en logfil. Der kan det godt gjelde &#8220;if it ain&#8217;t broken, don&#8217;t fix it&#8221; (med mindre det -må- fikses). Heldigvis jobber jeg ikke så ofte med slike systemer. De siste fire årene har jeg utelukkende jobbet med systemer som endrer seg hver dag og støtter stadig endrende markeder og forretningsprosesser.</p>
<h3>Kunnskap</h3>
<p>Argumentet &#8220;hvis utviklere slipper til øker sjansen for å rote noe til&#8221; synes jeg er noe billig. Jeg bestrider heller ikke at det skjer at utviklere klarer å rote ting til på aldeles grufulle måter. Jeg har da sannelig også erfart at driftere har rotet ting til royalt. Det er naturligvis sant at vi kan rote ting til om vi jobber med prod, vi er jo bare mennesker, men problemet er mye mer komplisert. Vi kan være enige i at vi i begge leirer har ulike nivåer av kompetanse innen forskjellige felter. Noen trenger mer tilsyn og hjelp enn andre, det er allikevel ikke det som er kjernen.</p>
<h3>Stort sett så handler det om endring vs. stabilitet</h3>
<p>I dag er IT-systemer såpass tett integrert i forretningsprosessen til bedrifter at de ikke kan endre på det ene uten det andre. Eller i andre ord: endringer av IT-systemer er viktig for endring av bedrifter og omvendt. Kanskje gjelder dette spesielt i store bedrifter (eller store statlige etater).</p>
<p>En stor hindring for driftssiden er naturligvis avtalene som idag brukes. De er ofte rettet mot stabile systemer (SLA-mål), og ikke endrende systemer. Det er naturlig at om jeg skulle ta på meg drifterhatten så ville jeg vært ganske skeptisk til å la Per Programmerer få gjøre hva han ville så lenge det ikke har noen konsekvenser for Per, men jeg mister masse driftsinntekter på grunn av nedetiden han skapte.</p>
<p>Alle mine erfaringer tyder også på at endringer betyr problemer. I en ideell verden ville aldri systemer (forretning eller IT) endre på seg og ingenting vil feile. Systemadministrasjon (drift) ville da være ganske enkelt. Det vil ikke være behov for å finne ut hvorfor noe skjedde feil med siste endring. Og det vil ihvertfall ikke haste å fikse problemene. Dessverre er virkeligheten kompleks. Å hindre programmere tilgang til produksjon er i beste fall å angripe symptomet; ikke årsaken.</p>
<p>Samtidig er tilgang alene naturligvis ingen sølvkule.</p>
<h3>Felles ansvar gir også bedre samarbeid</h3>
<p>Tilgang til produksjon må også medføre økt ansvar for produksjon. Vi må som programmerere slutte å ta snarveier og lære å administrere systemene vi utvikler. Hvis ikke vi klarer det selv, hvordan kan vi forvente andre skal kunne det? Samtidig som jeg synes det er utopisk å tenke at alle programmerere kan drifte systemer, synes jeg det er en like stor utopi å tenke at alle systemadministratorer / applikasjonsdriftere kan løse driftsproblemene alene. (Det finnes naturligvis noen få systemadministratorer/appdriftere med programmeringskunnskaper, og programmerere med appdrift/systemadministrasjonskunnskaper &#8211; vi kan se bort fra de nå, det er ikke alle som er heldige nok å ha den kombinasjonen i teamet sitt). Jeg tror dessverre at utviklere ikke vil lære mer om driftbarhet om de ikke jobber med det og ser hvor mye dritt applikasjonene klarer å produsere. Hvis programmerere ikke får lov å jobbe med det, kan kanskje heller ikke drift forvente særlig driftbare applikasjoner? En fin og svært enkel tilnærming å få til bra samarbeid og læring på kryss av drift/utvikling er… Wait for it… Å integrere systemadministrasjon/programmerere (drift/utvikling)!</p>
<h3>Arbeide sammen&#8230; daglig</h3>
<p>Sitte sammen, løse problemer sammen daglig. Det både høres enkelt ut og er igrunnen ganske enkelt. Til tross for svært gode resultater de gangene det gjøres, så er det min erfaring at det skjer alt for sjeldent. Når vi sitter sammen kan vi få til ekte læring, forbedring og innsikt. Bestillingsdokumentregimet, e-post, og et sjeldent møte eller telefon nå og da er i mitt syn en ganske ineffektiv form for kommunikasjon. </p>
<p>Min erfaring fra stor statlig etat var at det dessverre var litt for sjeldent (men ikke aldri!) at vi jobbet driftere og utviklere sammen for å løse felles problem. Normen var nettopp bestillinger, eskalering av bestillinger, e-post, purring på e-post, telefon, oppgitt telefon… Etter hvert gikk det så langt at vi måtte ta et møte – plutselig flyttet vi fjell og løste all verdens av problemer.</p>
<p>Spesielt når det handler om kommunikasjon av svært komplekse problemstillinger er det lett å misforstå, anta ting feilaktig, og det er lett at dårlig stemning oppstår. </p>
<p>Vi samarbeider mye mer og bedre med drift der jeg jobber nå. Det fungerer, selv om det ikke er helt daglig &#8211; enda. Vi (utviklere) har samtidig full tilgang til produksjon, og får lov å prodsette selv. Det er naturligvis en iboende risiko til at vi vil rote det til skikkelig; vi har klart oss bra og nærmer oss snart hundre releaser. Samtidig er det vi som får SMS og epost først når feilene kommer. Vi har mange mål for kvalitet, et er å alltid være tilgjengelig, et par andre, mer gjennomførbare er å aldri vekke noen på natta og å ikke få en eneste telefon etter en prodsetting. For å få dette til må vi alle være ansvarlige for å holde applikasjonene kjørende i produksjon. </p>
<p>Til slutt for å ta bilanalogien: Jeg bygde Ferrarien &#8211; ihvertfall motoren, kjørecomputeren og styringssystemet. Jeg integrerte også med stabilitetssystemet, bremsene, airbaggene, lysene, tenningssystemet og girkassen. Jeg var med å passe på at det hele passet inn i chassiset og tilpasset sammen med designerne de øvrige komponentene. Hvis jeg skal finne ut hvorfor den plutselig stoppet i tunnellen på E18 da det var 19 grader i lufta ingen kø, så holder det ikke å få tilsendt bilder av motoren eller kjørecomputeren… Selv om jeg kanskje ikke kan så mye om veier og vær, så tror jeg det er enklere om jeg får se på motoren og finne ut hvordan den ble brukt da det skjedde framfor å studere bildene. </p>
<p>Eller kanskje bedre, for å parafrasere min kollega, Jonas, sin kortere versjon: &#8220;å fikse motoren via e-post er som å fikse motoren gjennom eksosrøret&#8221;.</p>
<p>(Kunne naturligvis også løst det til en viss grad ved å investere masse penger på å bygge et digitalt diagnosesystem med masse sensorer som tok opp relevante data via kjørecomputeren, og få tilsendt dette, men da snakker vi F1-Ferrari…)</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/felles-ansvar-for-produksjon/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Slipp utvikleren til!</title>
		<link>http://open.bekk.no/slipp-utvikleren-til/</link>
		<comments>http://open.bekk.no/slipp-utvikleren-til/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 20:38:33 +0000</pubDate>
		<dc:creator>Torstein Gjengedal</dc:creator>
				<category><![CDATA[IT-rådgivning]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Systemarkitektur]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[it-strategi]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6534</guid>
		<description><![CDATA[Jeg leste nettopp boken 97 Things Every Programmer Should Know. Dette er en bok satt sammen av Kevlin Henney med utspring i en egen wiki. De 97 kapitlene er skrevet av ulike forfattere, der hvert kapittel omfatter et tema, prinsipp eller tips som programmerere bør kjenne til eller benytte. Noen av påstandene i ett av [...]]]></description>
			<content:encoded><![CDATA[<p>Jeg leste nettopp boken <em><a href="http://shop.oreilly.com/product/9780596809492.do#" target="_blank">97 Things Every Programmer Should Know</a></em>. Dette er en bok satt sammen av Kevlin Henney med utspring i en egen <a href="http://programmer.97things.oreilly.com/">wiki</a>. De 97 kapitlene er skrevet av ulike forfattere, der hvert kapittel omfatter et tema, prinsipp eller tips som programmerere bør kjenne til eller benytte. Noen av påstandene i ett av kapitlene strider imidlertid imot mine egne erfaringer.</p>
<p>I <a href="http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Touch_that_Code%21" target="_blank">kapittel 31 &#8211; <em>Don´t Touch That Code</em></a>, hevder forfatteren at utviklere ikke skal fikse feil i produksjon, og at dette bør forhindres ved at utviklere ikke gis tilgang til noe annet enn utviklingsmiljøet. Nærmere bestemt:</p>
<blockquote><p>&#8230; a developer &#8212; even a senior developer &#8212; should never have access beyond the development server</p></blockquote>
<p>og</p>
<blockquote><p>Under no circumstances &#8212; ever, at all &#8212; should a developer have access to a production server.</p></blockquote>
<p>Det er fornuftig at feilretting ikke bør skje direkte i produksjonsmiljøet. Selv har jeg imidlertid aldri opplevd dette, og har ikke intrykk av at dette utgjør et stort problem i de fleste utviklingsprosjekter. Derimot har man mange andre utfordringer, og en del av disse kan løses bedre nettopp ved å la utviklerne ha tilgang.</p>
<h4>Feilanalyse</h4>
<p>Ved daglig drift kan det oppstå feil eller andre hendelser som man har lyst til å se nærmere på. I slike tilfeller er det viktig å ha gode logger og at utviklerne har rask og enkel tilgang til disse. Dette er enklest å oppnå ved at utviklerne har direkte lesetilgang til loggene. Dersom man har en politikk som ikke tillater dette, ender man gjerne med lange og tidkrevende epostvekslinger mellom utviklings- og driftspersonell for å få tak i loggene det gjelder, noe som er tungvint og irriterende for alle parter &#8211; spesielt dersom det er snakk om kritiske feil der tidsfaktoren er viktig.</p>
<h4>Monitorering</h4>
<p>Loggene kan også benyttes til å gjenskape feilsituasjoner og/eller monitorere feilsituasjoner &#8220;live&#8221;, noe som kan være en svært effektiv og nyttig fremgangsmåte i gitte situasjoner. Slik oppfølging blir ofte enklere og mer fleksibelt dersom man har bygget applikasjonen slik at logginnstillinger og eventuelle andre parametre kan justeres mens applikasjonen kjører. Slik monitorering og justering er det utviklerne, som kjenner applikasjonen som sin egen bukselomme, som bør gjøre. Hvis utviklerne ikke har live tilgang til miljøet, nekter man seg i praksis et viktig verktøy ved feilsituasjoner.</p>
<h4>Administrasjon og støtteverktøy</h4>
<p>Ofte kan støttefunksjoner til en applikasjon være nyttige, enten det er operasjoner som er del av daglig drift eller ad-hoc-funksjoner som kan være nyttige ved spesielle situasjoner. Eksempler på dette kan være automatisk monitorering og varsling basert på logg-data eller interaksjon med applikasjonen som f.eks. invalidering av cache eller av-/påslåing av funksjoner på gitte tidspunkt. Mange slike støttefunksjoner kan utføres ved enkle kommandolinjescript. Igjen er det ofte utviklere som er best egnet til å lage slike støttefunksjoner, spesielt av ad-hoc-art, da det er de som best vet hvikle muligheter man har i applikasjonen.</p>
<h4>Utrulling</h4>
<p>Applikasjonsutrulling er også et område der utviklere kan spille en viktig rolle. Utviklere gjør gjerne utrulling på lokal maskin flere ganger daglig, og kjenner dermed denne fasen bedre enn noen. De er også ofte de som er best skikket til å forenkle, forbedre og automatisere denne prosessen.</p>
<p>&nbsp;</p>
<p>Å arbeide for å forbedre kommunikasjon, samarbeid og forståelse mellom utviklings- og driftsorganisasjonene kan være veldig nyttig og givende i mange prosjekter. Nærhet og samarbeid mellom utvikling og drift kan ofte være av avgjørende betydning for smidighet både ved utrulling av applikasjoner og ved oppfølging og overvåkning av daglig drift. DevOps er et uttrykk som er mye i vinden om dagen, og som fokuserer på nettopp dette. Artikkelen <em><a href="http://www.readwriteweb.com/enterprise/2011/08/devops-what-it-is-why-it-exist.php" target="_blank">DevOps: What It Is, Why It Exists and Why It&#8217;s Indispensable</a></em> gir en fin introduksjon til DevOps.</p>
<p>Utviklere bør altså ikke gjøre bugfixer i form av kodeendringer, omkonfigurering av programvare eller denslags direkte i produksjon. Dersom dette er et problem, bør det kunne forhindres &#8212; for eksempel ved noe så enkelt som rettighetsinnstilling på brukerne. Det er naturligvis ikke slik at utviklerne fullstendig skal ta over produksjonsmiljøet, men man gjør seg selv en bjørnetjeneste dersom man ikke benytter seg av den applikasjonsspesifikke ekspertisen utviklerne bestitter &#8212; også ved kjøretid i produksjon.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/slipp-utvikleren-til/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Kjør automatisk miljøverifikasjon!</title>
		<link>http://open.bekk.no/kjor-automatisk-miljoverifikasjon/</link>
		<comments>http://open.bekk.no/kjor-automatisk-miljoverifikasjon/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 06:59:59 +0000</pubDate>
		<dc:creator>Bent Kristiansen</dc:creator>
				<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[automatisk miljøverifikasjon]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[installasjon]]></category>
		<category><![CDATA[kvalitet]]></category>
		<category><![CDATA[miljøverifikasjon]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=5455</guid>
		<description><![CDATA[Vi som jobber med utvikling og forvaltning av IT-systemer, har ofte behov for å kontrollere om et miljø er i orden. Dette gjøres i mange tilfeller manuelt. Denne bloggposten er tenkt som inspirasjon for komme igang med automatisk miljøverifikasjon - noe som garantert vil være kvalitetsfremmende og tidsbesparende. Identifiser situasjoner hvor manuell verifikasjon gjøres i dag Vi [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Vi som jobber med utvikling og forvaltning av IT-systemer, har ofte behov for å kontrollere om et miljø er i orden. Dette gjøres i mange tilfeller manuelt. Denne bloggposten er tenkt som inspirasjon for komme igang med automatisk miljøverifikasjon - noe som garantert vil være kvalitetsfremmende og tidsbesparende.</strong></p>
<p/>
<h2>Identifiser situasjoner hvor manuell verifikasjon gjøres i dag</h2>
<p>Vi ønsker eksempelvis å vite om eksterne og interne avhengigheter er på plass, og at det ikke har oppstått åpenbare systemfeil når utvikler setter opp et utviklingsmiljø, ny kode distribueres til et test eller produksjonsmiljø, eller når forvalting kontaktes i forbindelse med systemfeil. Disse tre situasjonene forklares mer deltajert nedenfor.<br />
<strong>Oppsett av utviklingsmiljø</strong><br />
Når utviklere setter opp hvert sitt utviklingsmiljø verifiseres det at oppsettet er i orden ved å:</p>
<ul>
<li>Kjøre enhetstester, integrasjonstester og akseptansetester</li>
<li>Manuelt teste hovedfunksjoner i en eller flere applikasjoner/nettsider</li>
</ul>
<p><strong>Distribusjon av kode til test eller produksjonsmiljø</strong><br />
Når ny kode er distribuert til et miljø, gjør man vanligvis verifisering ved å:</p>
<ul>
<li>Manuelt teste hovedfunksjoner i en eller flere applikasjoner/nettsider</li>
<li>Manuelt teste ny funksjonalitet</li>
</ul>
<p><strong>Forvaltning</strong><br />
Når det kommer henvendelser om systemfeil til brukerstøtte eller driftsansvarlige, gjøres ofte feilsøking ved å:</p>
<ul>
<li>Manuelt teste en eller flere funkjsoner i systemet</li>
<li>Kontrollere systemloggen</li>
</ul>
<p>Manuell verifikasjon i situasjonene beskrevet ovenfor er tidkrevende og kan være vanskelige å utføre.</p>
<h2>Hvordan gjøre automatisk miljøverifikasjon?</h2>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/06/mv_sample_fig1.png"><img title="Automatisk miljøverifikasjon" src="http://open.bekk.no/wp-content/uploads/2011/06/mv_sample_fig1.png" alt="Eksempel på visualisert automatisk miljøverifikasjon" width="530" height="435" /></a></p>
<p>I BEKK har vi god erfaring med å lage skript, nettside og/eller applikasjon som sjekker avhengigheter og funksjoner i et IT-system.</p>
<h3>Skript</h3>
<p>For å verifisere et miljø i forbindelse med oppsett eller installasjon kan det være bra å lage et skript som returnerer resultat fra verifiseringen uten å vise det visuelt. Skriptet startes helt til slutt etter bygg og deploy er utført. Dersom noe i miljøverifiseringsskriptet feiler, returneres en feilkode, og mer detaljert feilmelding logges. Skriptet bør lese konfigurasjonsfiler til tjenester og konfigurasjonsfil for eventuelle klienter som distribueres, etter distribusjon. Da får vi kontrollert at det ikke er feil i kode som bygger konfigurasjonen under distribusjon til de forskjellige miljøene.</p>
<h3>Nettside</h3>
<p>Skal man verifisere et kjørende miljø for en internett- eller intranettløsning er det bra å ha en side som kjører forskjellige tester i løsningen, og som viser resultatet visuelt. Adressen til siden gir man til interesserte som har behov for den, som: testteamet, systemadministrator, superbrukere, support og drift. Siden bør tilgangsstyres.</p>
<h3>Applikasjon</h3>
<p>Hvis systemet har distribuerte klienter anbefaler vi at det distribueres en egen applikasjon for diagnose, eller at det settes opp et menyvalg under hjelp-menyen som starter systemdiagnosen (dersom man har autorisasjon).</p>
<p>Det er essensielt at innstillinger og endepunkter leses fra klientens konfigurasjon. Diagnose-applikasjonen bør kjøre i samme brukerkontekst som den distribuerte klienten.</p>
<h2>Hva kan/bør verifiseres på denne måten?</h2>
<p>Egentlig er det ingen grenser for hva man kan verifisere på denne måten, men ikke gjør det for avansert. Da blir det vanskelig å vedlikeholde. Miljøverifikasjon skal ikke erstatte systemintegrasjonstester eller akseptansetester.</p>
<p>Verifisering av tjeneste-endepunkt til eksterne og interne tjenester, databasetilkoblingsstrenger og noen basis-operasjoner er tilstrekkelig, og svært nyttig etter vår erfaring.</p>
<p>Noen regler:</p>
<ul>
<li>Miljøverifikasjon bør gjøres så enkelt som mulig</li>
<li>Miljøverifikasjon bør ikke ta lang tid å kjøre (&lt;1 min)</li>
<li>Vurder å benytte tråder (for å få raskere total responstid)</li>
</ul>
<p>Start med å få på plass sjekk om én tjeneste svarer, for å komme i gang. Legg til mer etterhvert. Det kan være en god idé å inkludere løsning på kjente feilsituasjoner, slik at feilsøking går fortere.</p>
<h2>Hva er dine erfaringer?</h2>
<p>Hva er dine erfaringer med verifisering og feilsøking i forbindelse med oppsett og distribusjon av kildekode til ulike miljøer?</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/kjor-automatisk-miljoverifikasjon/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The benefits of simple, automated performance testing</title>
		<link>http://open.bekk.no/the-benefits-of-simple-automated-performance-testing/</link>
		<comments>http://open.bekk.no/the-benefits-of-simple-automated-performance-testing/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 08:46:42 +0000</pubDate>
		<dc:creator>Vidar Kongsli</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Systemarkitektur]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[ndc2011]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=5888</guid>
		<description><![CDATA[Norwegian Developer&#8217;s Conference (NDC) 2011 was arranged in Oslo Spektrum 8th &#8211; 10th of June. Kristoffer Dyrkorn from BEKK presented a talk called &#8220;The benefits of simple, automated performance testing&#8221; where he spoke about automated performance-testing of web solutions. Automated testing of non-functional demands is particularly important in agile projects, and should receive the same [...]]]></description>
			<content:encoded><![CDATA[<p><a title="NDC: homepage" href="http://www.ndc2011.no/">Norwegian Developer&#8217;s Conference (NDC) 2011</a> was arranged in Oslo Spektrum 8th &#8211; 10th of June. Kristoffer Dyrkorn from BEKK presented a talk called &#8220;The benefits of simple, automated performance testing&#8221; where he spoke about automated performance-testing of web solutions. Automated testing of non-functional demands is particularly important in agile projects, and should receive the same focus and priority as automated unit- and integration-testing.</p>
<p>You can see the talk here:</p>
<p align="middle"><iframe src="http://player.vimeo.com/video/27145624?title=0&amp;byline=0&amp;portrait=0" width="400" height="225" frameborder="0"></iframe></p>
<p>The rest of the videos from NDC is available at <a title="NDC: agenda" href="http://www.ndc2011.no/agenda.aspx?cat=1071">NDC&#8217;s agenda page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/the-benefits-of-simple-automated-performance-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Invester i utviklingsmiljøet ditt &#8211; hvorfor jeg begynte med Vagrant</title>
		<link>http://open.bekk.no/invester-i-utviklingsmiljoet-ditt-hvorfor-jeg-begynte-med-vagrant/</link>
		<comments>http://open.bekk.no/invester-i-utviklingsmiljoet-ditt-hvorfor-jeg-begynte-med-vagrant/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 14:17:04 +0000</pubDate>
		<dc:creator>Andreas Heim</dc:creator>
				<category><![CDATA[Fri Programvare]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[byggeverktøy]]></category>
		<category><![CDATA[friprog]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[utviklingsmiljø]]></category>
		<category><![CDATA[vagrant]]></category>
		<category><![CDATA[virtualbox]]></category>
		<category><![CDATA[virtualisering]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=4291</guid>
		<description><![CDATA[<p>Vi forsøker ofte å få utviklingsmiljøet vårt til å være så likt som mulig som produksjonsmiljøet. I mange tilfeller er vi av praktiske hensyn ofte nødt til å ta noen snarveier, å f.eks. bruke en annen database, appserver, webserver etc.</p>
<p>
Ved å innføre virtualisering av utviklingsmiljøet så oppnår man en rekke fordeler. Det er på tide å ta utviklingsmiljøet et hakk videre. </p>
]]></description>
			<content:encoded><![CDATA[<p>Vi forsøker ofte å få utviklingsmiljøet vårt til å være så likt som mulig som produksjonsmiljøet. I mange tilfeller er vi av praktiske hensyn ofte nødt til å ta noen snarveier, å f.eks. bruke en annen database, appserver, webserver etc.</p>
<p>Ved å innføre virtualisering av utviklingsmiljøet så oppnår man en rekke fordeler. Det er på tide å ta utviklingsmiljøet et hakk videre.</p>
<h2>Hva</h2>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/02/525px-TIM-100_teller_workstation.jpg"><img class="alignright size-full wp-image-4310" title="Ironisk illustrasjon av et utviklingsmiljø" src="http://open.bekk.no/wp-content/uploads/2011/02/525px-TIM-100_teller_workstation.jpg" alt="Ironisk illustrasjon av et utviklingsmiljø" width="150" height="171" align="right" /></a><br />
Virtualisering av utviklingsmiljøet innebærer å pakke avhengigheter som database, appserver etc. inn i en virtuell maskin. Denne virtuelle maskinen kan man sette opp slik at den etterlikner produksjonsmiljøet ned til de minste detaljer. En av de store fordelene her er operativsystem i produksjonsmiljøet. Mange utviklere sitter på enten OS X eller Windows, og deployer til *nix-baserte servere.</p>
<p>De aller fleste utviklingsprosjekter har en eller flere eksterne avhengigheter, det være database, eksterne tjenester, LDAP, applikasjonsservere etc. Selv om vi som utviklere prøver å unngå det, så avhenger også kodebasen som oftest av spesifikke versjoner av en eller flere avhengigheter. Disse avhengighetene kan man få samlet i en pakke.</p>
<h2>Hvorfor</h2>
<p><strong> </strong></p>
<pre><strong>if (!produksjonsmilø.equals(utviklingsmiljø)) { throw new EnvironmentException("#fail!");}</strong></pre>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p>Hvor mange mennesker kan si at de aldri har hatt en bug i produksjon som de ikke klarte å gjenskape på det lokale utviklingsmiljøet?</p>
<p><strong> </strong></p>
<pre><strong>cost_of_change = Developers.all.count * time_spent_doing_pointless_task * hourly_rate</strong></pre>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p>Hvor lang tid bruker en ny utvikler på teamet for å sette opp utviklingsmiljøet? Hvis man driver forvaltning på flere prosjekter samtidig, hvor lang tid bruker man på å bytte mellom de?</p>
<p>Hva gjør du når harddisken kræsjer på utviklingsmaskinen? Hvor lang tid bruker du på å installere f.eks. ruby (i riktig versjon), maven, database, sette opp riktige miljøvariabler etc. Ca. én arbeidsdag er vel ikke helt utenkelig.</p>
<p>Vi introduserer bugs i koden hver eneste dag, og det å oppdage disse tidlig er svært viktig. Hvis man har en lang utviklingssyklus og det tar lang tid før en feature er i produksjon kan det fort bli dyrt å rette en bug som ble innført for flere uker siden.</p>
<p>Fordi vi liker å finne bugs tidlig har mange av oss blitt glad i enhets- og integrasjonstesting, samt at de aller fleste prosjekter benytter seg av kontinuerlig integrasjon. Kontinuerlig integrasjon er i mine øyne helt uunnværlig, men hvis jeg kan finne en bug FØR den havner i kildekontrollsystemet så vil det være det mest optimale.</p>
<p>Vi kan gjennom dette identifisere noen egenskaper som kjennetegner et godt utviklingsmiljø:</p>
<p><strong>Utviklingsmiljøet bør være:</strong></p>
<ol>
<li>Likt produksjonsmiljøet</li>
<li>Likt for alle utviklere på teamet</li>
<li>Uavhengig av eksterne systemer (les: systemet bør kunne kjøres i sin helhet på lokal maskin)</li>
<p><strong>I tillegg vil jeg introdusere et par til</strong></p>
<li>Oversiktlig</li>
<li>Raskt å sette opp for nye utviklere</li>
<li>Under kildekontroll</li>
</ol>
<h2>Hvordan?</h2>
<p><a href="http://vagrantup.com"><img class="alignright size-full wp-image-4301" title="Vagrant logo" src="http://open.bekk.no/wp-content/uploads/2011/02/vagrant_chilling.png" alt="Vagrant Logo" width="200" height="200" align="right" /></a></p>
<p><a href="http://vagrantup.com"> </a></p>
<pre><a href="http://vagrantup.com"><strong>include 'vagrant'</strong></a></pre>
<p><a href="http://vagrantup.com"> </a></p>
<p><a href="http://vagrantup.com"></a>Mye av dette kan løses med god dokumentasjon, godt oppsatte byggeverktøy og diverse scripts, men når vi helautomatiserer prosessen vil vi oppnå noen klare fordeler.</p>
<p>Inn kommer <a href="http://vagrantup.com">Vagrant</a>.</p>
<p>Vagrant gjør to ting:</p>
<ol>
<li>Automatisert skripting av virtuelle maskiner</li>
<li>Automatisert oppsett/installasjon av &#8216;avhengigheter&#8217;. (kalt provisioning)</li>
</ol>
<p>Vagrant er pakket som en ruby-gem og er et skript-verktøy/dsl på toppen av <a href="http://virtualbox.org">VirtualBox</a> og automatiserer import, oppstart og konfigurasjon av virtuelle maskiner.</p>
<p>Vagrant gjør også installasjon av applikasjonsservere, databaser og andre avhengigheter lekende lett ved å inkludere støtte for <a href="http://github.com/opscode/chef">Chef</a> og <a href="https://github.com/lak/puppet">Puppet</a>, to verktøy for serveroppsett og konfigurasjonshåndtering.</p>
<p>Synes du (som meg) at Chef og Puppet blir litt tungt å sette seg inn i, er det veldig enkelt å lage sin egen provisioner-plugin og bruke f.eks <a href="https://github.com/crafterm/sprinkle">Sprinkle</a> istedenfor.</p>
<p><strong> </strong></p>
<pre><strong>Strategy =&gt; "#{win}"</strong></pre>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p>For å lage virtuelle bokser kan man benytte følgende strategi.</p>
<p>Ta utgangspunkt i ett basis-image som tilsvarer operativsystemet som du benytter i produksjon. Lag så et vagrant-prosjekt som installerer app-server, database, etc. i riktig versjon. Gjør denne boksen så lik produksjon som mulig. La denne boksen være en &#8220;grunnboks&#8221; for videre jobbing. Oppsettet på denne boksen skal ikke endre seg ofte. En full gjenbygging av denne boksen vil kunne ta litt tid.</p>
<p>I selve utviklingsprosjektet ditt oppretter du en ny vagrant-boks som baserer seg på &#8220;grunnboksen&#8221;. Her legger du inn skreddersydd konfig og oppgaver for prosjektet, setter opp deling av mapper, port-forwarding, oppgaver for tømming av database. Denne boksen bør kunne slettes og kjøres opp i løpet av kort tid, så oppgaver som tar lang tid bør legges til grunnboksen, eventuelt i egne tasks.</p>
<p>På grunn av mappedeling kan man fortsette å bruke sin egen editor, og endringene vil gjøres samtidig i den virtuelle maskinen og på verten. Byggeverktøy kan kjøres både i den virtuelle maskinen og lokalt.</p>
<h3>
<pre><strong>“However beautiful the strategy, you should occasionally look at the results.”
 - Winston Churchill</strong></pre>
</h3>
<p><strong> </strong></p>
<pre><strong><a href="http://open.bekk.no/wp-content/uploads/2011/02/Churchill_portrait_NYP_45063.jpg"><img class="alignright size-full wp-image-4305" title="Churchill som ser sur ut" src="http://open.bekk.no/wp-content/uploads/2011/02/Churchill_portrait_NYP_45063.jpg" alt="Churchill som ser sur ut" width="200" height="246" align="right" /></a>
</strong></pre>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p>Som i de fleste tilfeller ender vi opp med en liste med fordeler og ulemper:</p>
<h3>Fordeler</h3>
<ul>
<li>Utviklingsmiljøet ligger under kildekontroll og kan gjenskapes ved å kjøre en enkel kommando</li>
<li>Nye teammedlemmer kommer raskt igang med utvikling.</li>
<li>Endringer i produksjonsmiljø kan replikeres i utviklingsmiljø, og rulles ut raskt på utviklermaskiner</li>
<li>Kortere feedback-loop</li>
<li>Eksterne systemer som f.eks. LDAP trenger ikke mockes</li>
<li>Åpner for 100% separert kontinuerlig integrasjon for systemer som deler tjenester</li>
<li>Hvis man allerede bruker Chef eller Puppet til å sette opp prodservere så kan man gjenbruke konfigurasjonen</li>
<li>Modular oppbygning, så det er lett å lage utvidelser og plugins</li>
</ul>
<h3>Ulemper</h3>
<ul>
<li>Byggehastigheten går ned hvis bygget kjøres på den virtuelle maskinen. (F.eks. maven tenderer til å være ca 1,5 ggr. tregere når bygget blir kjørt virtuelt)</li>
<li>Enda en teknologi i prosjektet</li>
<li>Vertsmaskiner med lite RAM kan bli trege</li>
</ul>
<h3>Tips og triks</h3>
<p>Setter man opp ssh-agent forwarding kan den virtuelle maskinen sjekke ut kode fra f.eks. github.</p>
<p>I Java-prosjekter som bruker Maven lønner det seg å sette opp det lokale maven-repoet som en delt mappe.</p>
<p>Vagrant har støtte for å kjøre opp flere virtuelle maskiner i samme prosjekt, og man kan da f.eks. simulere database på en egen maskin. Det åpner også for å teste avansert clustring og fallback-mekanismer lokalt.</p>
<p>Jeg har også laget et lite eksempel på en virtuell maskin for java-utvikling, sjekk ut kildekoden fra github <a href="http://github.com/heim/vagrant-java-example">her</a>. Denne inneholder også en enkel implementasjon av en provisoner for Sprinkle. Ellers er dokumentasjonen til Vagrant anbefalt lesestoff, <a href="http://vagrantup.com/docs/getting-started/index.html">Getting started</a> er et fint sted å begynne.</p>
<p>Ressurser:</p>
<ul>
<li><a href="http://github.com/heim/vagrant-java-example">vagrant-java-example</a></li>
<li><a href="http://vagrantup.com/docs/getting-started/index.html">Getting started</a></li>
<li><a href="https://github.com/mitchellh/vagrant">mitchellh-vagrant</a></li>
<li><a href="http://maxim.github.com/sprinkle-cheatsheet/">sprinkle cheat sheet</a></li>
<li><a href="http://vagrantup.com/docs/index.html">vagrant dokumentasjon</a></li>
<li><a href="https://github.com/mitchellh/vagrant-rake">vagrant-rake-plugin</a></li>
</ul>
<p>Følg meg på <a href="http://twitter.com/heim">twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/invester-i-utviklingsmiljoet-ditt-hvorfor-jeg-begynte-med-vagrant/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ytelsestesting med Grinder</title>
		<link>http://open.bekk.no/ytelsestesting-med-grinder/</link>
		<comments>http://open.bekk.no/ytelsestesting-med-grinder/#comments</comments>
		<pubDate>Mon, 07 Feb 2011 07:00:29 +0000</pubDate>
		<dc:creator>Espen Herseth Halvorsen</dc:creator>
				<category><![CDATA[Fri Programvare]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[grinder]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[kvalitet]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[ytelse]]></category>
		<category><![CDATA[ytelsestesting]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=4099</guid>
		<description><![CDATA[Før jul jobbet jeg en del med ytelsestesting, og satt opp en ytelsestest-rigg fra scratch på prosjektet vårt. Vi var på jakt etter et enkelt system som var raskt å ta i bruk, samtidig som det lett burde kunne utvides etterhvert som våre behov økte. Ettersom andre i Bekk hadde hatt suksess med Grinder før, [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Før jul jobbet jeg en del med ytelsestesting, og satt opp en ytelsestest-rigg fra scratch på prosjektet vårt. Vi var på jakt etter et enkelt system som var raskt å ta i bruk, samtidig som det lett burde kunne utvides etterhvert som våre behov økte. Ettersom andre i Bekk hadde <a href="http://www.slideshare.net/kvangaball/grinder-og-webdriver">hatt suksess med Grinder</a> før, falt valget på dette verktøyet. </strong></p>
<p>Etter en del prøving og feiling føler vi at vi har fått opp en relativt stabil og bra «rigg», og har også funnet ut at Grinder er nyttig å ha til mye mer enn ytelsestesting. Så derfor er det tid for erfaringsdeling! <img src='http://open.bekk.no/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-4099"></span></p>
<p>Jeg tenkte å dele denne posten opp i tre deler:</p>
<ol>
<li>Litt generelt om ytelsestesting, Grinder, og hvilke andre &#8220;testtyper&#8221; man kan bruke Grinder til.</li>
<li>Hvordan sette opp en fullt fungerende Grinder-rigg fra scratch</li>
<li>En del eksempler på fungerende ytelsestest-script for Grinder.</li>
</ol>
<p>Før du begynner, så anbefaler jeg deg å klone eller laste ned <a href="https://github.com/Espenhh/Grinder-eksempel">eksempelprosjektet jeg har lagt ut</a> på github &#8211; [<a href="https://github.com/Espenhh/Grinder-eksempel/zipball/master">Direkte link til ZIP-fil</a>]</p>
<hr />
<h3>TL;DR: for deg som ikke gidder lese mer:</h3>
<p><a href="https://github.com/Espenhh/Grinder-eksempel">Klon prosjektet fra GitHub</a><br />
<script src="https://gist.github.com/811850.js?file=tl%3Bdr.sh"></script></p>
<hr />
<img class="aligncenter size-full wp-image-4117" title="del1" src="http://open.bekk.no/wp-content/uploads/2011/02/del1.png" alt="" width="100%" />
<p>&nbsp;</p>
<p>Min mening er at alle har godt av å sette litt fokus på ytelse, selv om du kanskje bare lager et internsystem som brukes av et fåtalls mennesker. De fleste av oss fokuserer på kodekvalitet og brukervennlighet, hvorfor ikke sette av litt tid til ytelse også? Med automatiserte tester kan du lett måle hvordan ytelsen endrer seg over tid (Grinder kan <a href="http://wiki.hudson-ci.org/display/HUDSON/Grinder+Plugin">lett integreres med byggesystemer som Hudson</a> for å måle ytelsestrend over tid).   Du får også et helt annet forhold til applikasjonen din når du vet hvordan den oppfører seg ved forskjellig last, rett og slett et selvprodusert DDOS-angrep om du vil.  </p>
<p>Etter å ha brukt Grinder i flere måneder har vi også funnet en rekke flere bruksområder der vi har kunnet gjenbruke riggen vår, og til en viss grad også ytelsestestscriptene uten videre forandringer:</p>
<ol>
<li><strong>Ren ytelsestesting:</strong> Å kjøre i gang en del tråder og la de teste systemet over en viss tid, for så å få ut en rapport med detaljert statistikk fungerer glimrende (heldigvis, siden det var litt av hovedpoenget vårt med Grinder)</li>
<li><strong>Stresstesting:</strong> Her kjørte vi så og si de samme testene som under ytelsestestingen, bortsett fra at vi gjorde det i en mye større skala. Jeg kan ikke gå altfor mye i detaljer, men la oss bare si at 400mbit/s trafikk ut fra serverclusteret vårt i over en time var «barnemat» for Grinder! (og heldigvis også applikasjonen)</li>
<li><strong>Langtidstesting:</strong> For å gjøre en såkalt «langtidstest» så tonet vi rett og slett ned aggresiviteten til Grinder drastisk, og lot det stå og surre i tre-fire dager. Grinder er såpass fleksibelt at du kan sette det i gang, for så å bare «kill’e» det og likevel få gode rapporter. </li>
<li><strong>Lastbalanseringstesting:</strong> Systemene våre er trygt plassert bak BigIP for lastbalansering. I forbindelse med oppsett av dette brukte vi Grinder for å kontrollere at lastbalanseringsalgoritmene og oppsettet fungerte slik vi ville, både med stor og liten trafikk.</li>
<li><strong>Avbruddstesting: </strong>Vi har gjort flere typer avbruddstesting ved hjelp av Grinder. F.eks kunne vi lett teste hvordan «hot-backup» database-fallback-servere oppførte seg når vi var under stor last og simulerte databasefeil. Vi testet også hvordan maks potensiell trafikk endret seg når vi tok ned en og flere av applikasjonsserverene.</li>
<li><strong>Generell hjelp under utvikling: </strong>Grinder har også kommet til nytte under utviklingsprosessen, det er alltid nyttig å kunne sette i gang en viss mengde automatisert trafikk mot sin egen maskin når man utvikler ulike deler av løsningen.</li>
</ol>
<p>Regner med at du er overbevist om at du trenger Grinder nå, så vi hopper rett over på det praktiske.</p>
<hr />
<img class="aligncenter size-full wp-image-4118" title="del2" src="http://open.bekk.no/wp-content/uploads/2011/02/del2.png" alt="" width="100%" />
<p>&nbsp;</p>
<p> Riggen av Grinder jeg har tenkt til å vise deg er i stor grad basert på standard Grinder-konfigurasjon, men vi har likevel gjort en del småendringer for å få det mer fleksibelt. Målet med riggen var følgende:</p>
<ol>
<li>Å kunne skrive en rekke ulike test-script som gjør forskjellige ting (f.eks noen som bare fokuserer på ren lese-last, mens andre fokuserer mer på operasjoner som involverer databaseendringer, og igjen andre som inneholder «random» operasjoner for å simulere reell last)</li>
<li>Å kunne lage ulike scenarier, som gjør av vi kan kombinere et vilkårlig antall av scriptene nevnt over. F.eks kan ett scenarie være «ytelsestest på QA», mens et annet er «langtidstest uten skriveoperasjoner med innslag av random operasjoner».</li>
<li>Å enkelt kunne konfigurere hvor testen kjører, f.eks om den skal gå mot DEV-server, QA-cluster eller localhost.</li>
</ol>
<div id="attachment_4124" class="wp-caption alignright" style="width: 310px"><a href="http://open.bekk.no/wp-content/uploads/2011/02/ill.png"><img class="size-medium wp-image-4124" title="Illustrasjon av forholdet mellom Scenarier og Script" src="http://open.bekk.no/wp-content/uploads/2011/02/ill-300x177.png" alt="Illustrasjon av forholdet mellom Scenarier og Script" width="300" height="177" /></a><p class="wp-caption-text">Illustrasjon av forholdet mellom Scenarier og Script</p></div>
<p>Jeg har forsøkt å oppsummere strukturen med en liten illustrasjon. På den kan du se litt tydeligere konseptet med scenarier som gjenbruker ferdiglagde scripts, og samtidig setter opp en del konfigurasjon og parametere for dem.  Så vi har kort sagt følgende to elementer:</p>
<h3>Scenarier:</h3>
<ul>
<li>Bestemmer hvilke script som skal kjøres i denne testen.</li>
<li>Bestemmer parametere til scriptene (kan være alt, men rot-URL er et godt eksempel).</li>
<li>Bestemmer hvor mange prosesser Grinder skal kjøre i gang, og hvor mange tråder hver av disse skal kjøre.</li>
<li>Bestemmer hvor mange ganger hver tråd i hver prosess skal kjøre hvert script.</li>
<li>Kan i tillegg konfigurere en rekke andre innstillinger, slik som gradvis opptrapping av trafikken, minnebegrensninger, JVM-parametere, om det skal <a href="http://grinder.sourceforge.net/g3/console.html">kjøres mot Console</a> (interaktivt java-program for å styre test-parametere live) osv.</li>
</ul>
<h3>Scripts:</h3>
<ul>
<li>Inneholder instruksjoner for hvordan en enkelt test skal kjøre</li>
<li>Kan likevel bestå av flere «tester», f.eks for å skille mellom kall mot ulike deler av systemet gjort i samme test.</li>
<li>Skrevet i «Jython», dvs python-syntaks med mulighet for å inkludere hva som helst av Java-biblioteker (siden Grinder kjører på topp av JVM’en).</li>
</ul>
<p>Vi har i tillegg et script kalt sequence.py, som tar seg av å kjøre alle scriptene du vil ha med i scenariet ditt. Dette er en modifisert utgave av et offisielt eksempel fra Grinder-dokumentasjonen. Det finnes også mulighet for å kjøre de ulike scriptene innad i en tråd på en prosess i parallell, men det har ikke vi helt sett behovet for (siden vi uansett kjører så mange tråder i parallell).  </p>
<p>Jeg tror jeg kutter forklaringen her, og går heller rett over på eksemplene. Vi liker tross alt kode bedre enn forklaring av kode, gjør vi ikke? <img src='http://open.bekk.no/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<hr />
<img class="aligncenter size-full wp-image-4119" title="del3" src="http://open.bekk.no/wp-content/uploads/2011/02/del3.png" alt="" width="100%" /></p>
<h3>#1: Det klassiske vg-eksempelet</h3>
<p>Alle som har vært provisorisk IT-support for diverse familie og slekt har vel over telefon forsøkt å forklare hvordan man pinger vg.no til en forvirret mor eller bestemor. Dette eksempelet er ikke noe bedre, her forsøker jeg å forklare deg hvordan du kan laste <a href="http://vg.no">http://www.vg.no</a> fra Grinder. Og for å unngå at du ufrivillig DOS’er VG har jeg satt lave verdier for antall tråder og gjennomkjøringer (velger du å øke dem så tar jeg ingen ansvar for hva du måtte få av sinte telefonsamtaler&#8230;)    </p>
<p>Vi begynner med å lage et scenarie. Hvis du har <a href="https://github.com/Espenhh/Grinder-eksempel">lastet ned koden</a> og følger med, så ligger det i mappen «scenarier», kalt vg.properties. Følgende er de viktigste delene (i den nedlastbare koden har jeg beholdt alt det andre som følger med i eksempelscenariet til Grinder, så du kan se hva du har av muligheter)<br />
 <script src="https://gist.github.com/811927.js?file=vg.properties"></script>Her er alle variablene med grinder foran predefinerte Grinder-variabler. Vi sier at vi kjører scriptet kalt sequence.py, vi skal kjøre det med en prosess som igjen har fire tråder. Disse trådene skal kjøre scriptet totalt fem ganger hver. Barneskolematte her nå: hvor mange ganger kjører scriptet? Take your time, jeg venter&#8230; &#8230; &#8230; 1 x 4 x 5 = 20 ganger. Ikke så vanskelig det vel?</p>
<p>Scriptet sequence.py tar tak i alle variabler scriptXXX, og kjører hver og en av dem. Her har vi bare ett script, så da kjøres bare det, men vi kunne fint lagt på «script2=t002dagbladet». Legg merke til at vi ikke har med filendelsen her!</p>
<p>Vi lager deretter scriptet vårt, t001vg.py, og legger det i mappen «src». Følgende superenkle kode gjør kallet mot vg.no:</p>
<p><script src="https://gist.github.com/811929.js?file=t001vg.py"></script> </p>
<p>Import-statementene skjønner du sikkert, de to neste linjene er der for at sequence.py skal kunne kjøre dette scriptet, og de tre siste linjene er den «virkelige koden vår». Her lager vi en test, med et testnummer (siden dette scriptet er test 001, og vi gjerne vil kunne ha flere «undertester» i ett script, så nummererer vi testen 101, altså test #1 undertest #01. Trust me, du vil se fordelen med dette senere!). Vi gir den et enkelt navn også. Så lager vi en HTTPRequest, som vi wrapper i testvariabelen vår. Dette gjør at vi får Grinder til å instrumentere dette for oss. Til sist bruker vi denne wrappede requesten til å gjøre et GET-kall mot http://www.vg.no.  </p>
<p>For å kjøre denne herligheten bruker du kommandolinja.  Jeg har laget et lite script for deg, kalt /bin/startAgent.sh . Er du så uheldig at du sitter på windows, så får du lage deg et eget script &#8211; det er relativt ukompliserte greier, så tipper du klarer det fint <img src='http://open.bekk.no/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Scriptet tar inn en parameter: navnet på scenariet. Så stå i rotkatalogen vår, og kjør følgende kommando:  </p>
<p><code>./bin/startAgent.sh vg</code> </p>
<p>Når dette har surret og gått seg ferdig, så kan du se resultatene i mappen «log». Her har du to filer, data&#8230; og out&#8230; I den første finner du hele datagrunnlaget for alle testene som er gjort, men dette har du sannsynligvis ikke lyst til å se på selv (med mindre du er en excel-ninja). Filen out&#8230; er mye mer interessant. Her kan du se all output fra scriptene som har kjørt, og helt nederst har du en flott oppsummering av de ulike testene som har kjørt:  </p>
<p><script src="https://gist.github.com/811932.js?file=testresultaterVG"></script></p>
<p>Om du ser for deg at vi hadde kjørt flere script i samme scenarie, så skjønner du kanskje hvorfor vi nummererte testene som vi gjorde. Det ville vært litt kjipt om vi hadde nummerert flere tester i ulike script «1», da ville statistikken blitt ødelagt! Merk også at du ville fått flere eksemplarer av filene om du kjørte flere prosesser, da hver prosess har hver sine filer.</p>
<h3>#2: Et litt mer avansert eksempel: Twitter’s REST-api</h3>
<p>Nå skal vi begi oss ut på et litt mer intrikat eksempel. For å holde ting så enkelt som mulig, så lager vi et nytt scenarie som «jsoneksempel.properties». Denne er såpass lik den forrige (med unntak av at vi kaller et nytt script), så jeg limer den ikke inn her.</p>
<p>Her kaller vi ett enkelt script (slapp av, vi kommer snart til fler-scripts-scenarier), nemlig t002json.py. Følgende kode er vårt eminente script:</p>
<p><script src="https://gist.github.com/811935.js?file=t002json.py"></script> Føler du at du trenger en liten forklaring? Det skal du få:</p>
<ol>
<li>Vi starter etter alle import-statementene med å hente to variabler fra scenarie-fila</li>
<li>Grunnen til at vi setter &#8220;delayReports&#8221; er for å kunne kjøre &#8220;setSuccess&#8221; på slutten om vi får exception. Hvis vi ikke utsetter rapporteringa, så vil ikke dette funke.</li>
<li>Vi definerer deretter en error-output og en log-output, som skriver til filene error&#8230; og out&#8230;</li>
<li>Så wrapper vi to ulike requests, på samme måte som i VG-eksempelet</li>
<li>Vi kjører alt i en try-løkke for å kunne feile &#8220;gracefully&#8221; og logge det som en feilet test</li>
<li>Vi gjør en GET mot twitter&#8217;s søke-tjeneste, deretter gjør vi litt &#8220;JSON-magi&#8221;</li>
<li>Så looper vi gjennom et JSON-array med alle twitter-resultatene.</li>
<li>For hver enkelt tweet logger vi brukerens ID</li>
<li>Vi laster også ned profilbildet til hver enkelt bruker</li>
</ol>
<p>Da er det bare for deg å kjøre scriptet, og se hva som skjer.   </p>
<p><code>./bin/startAgent.sh jsoneksempel</code> </p>
<p>Jeg tipper du vil få et resultat som ligner litt på dette:<br />
 <script src="https://gist.github.com/811964.js?file=loggTwitter"></script></p>
<p>Prøv gjerne også å endre variabelen «sokeord» i scenarie-filen.</p>
<h3>#3: Et eksempel med mye snadder</h3>
<p>Det siste eksempelet er ikke direkte kjørbart, fordi her har vi involvert en rekke artigheter du kan få bruk for i dine ytelsestester. Det betyr at scriptet har noen eksterne avhengigheter som jeg ikke kan legge med i nedlastningen. Det er altså ikke ment for å tas direkte i bruk, det er mer tenkt som en inspirasjon til hva man kan gjøre. Ved å gjøre enkle tweaks kan du kjapt få det til å fungere.</p>
<p><script src="https://gist.github.com/811982.js?file=t003komplisert.py"></script></p>
<p>For å nevne noen av tingene som skjer her:</p>
<ol>
<li>Vi importerer inn en egenlaget klasse kalt TestDataGenerator. Denne må du lage selv, ideen vår her er at den kan gi oss en brukerkonto med en viss ID. F.eks kan du bruke denne til å laste inn en stor tekstfil med testdata statisk, slik at du slipper å gjøre dette hver gang i Grinder, for deretter å be om å få en enkelt brukerID fra denne listen i hver testgjennomkjøring</li>
<li>Vi importerer vanlig Random fra java.util, og bruker denne til å generere et random tall i hver test som vi bruker som input til klassen jeg nettopp snakket om.</li>
<li>Vi setter på noen HTTP-headere. Dette kan f.eks brukes for å aktivere <a href="http://open.bekk.no/2010/12/30/unnga-a-dra-med-deg-bakdora-i-produksjon-med-maven/">en bakdør vi kun bruker under testkjøring</a>.</li>
<li>Vi kjører Basic Auth mot serveren. Dette er nyttig dersom du f.eks har QA-serveren din åpent på nettet for å kunne kjøre distribuerte tester mot den, men likevel ønsker å sperre den for andre enn deg selv.</li>
<li>I tillegg catcher vi exceptions, og setter testen til feilet. Dette skjer f.eks om vi får noe annet enn gyldig JSON tilbake fra serveren. Legg også merke til at vi da må sette «delay reports» i grinder, ellers fungerer ikke dette.</li>
</ol>
<p>Muligens er det også mer snasne ting vi gjør her som jeg har glemt å nevne. Hovedpoenget med dette tredje eksempelet var uansett ikke å gi deg noe som funker «out of the box», men heller gi deg en rekke små triks du selv kan bruke i dine script.</p>
<h2>Konklusjon</h2>
<p>Konklusjonen er at du nå ikke lenger har noen unnskyldning for å ikke ytelsesteste systemene du lager. Og ingen unnskyldning for å ikke langtidsteste, stressteste, avbruddsteste og lastbalanseringsteste heller for den saks skyld.</p>
<p>Så last ned all koden, test det ut, og sett det opp for ditt prosjekt. Lykke til <img src='http://open.bekk.no/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Ressurser:</h3>
<ul>
<li>Grinder’s nettsider: <a href="http://grinder.sourceforge.net/">http://grinder.sourceforge.net/</a></li>
<li>Jython’s nettsider: <a href="http://www.jython.org/">http://www.jython.org/</a></li>
<li>Grinder TCPProcy: <a href="http://grinder.sourceforge.net/g3/tcpproxy.html">http://grinder.sourceforge.net/g3/tcpproxy.html</a> &#8211; Dette er en utrolig fet greie! Du starter den, setter opp en proxy i nettleseren din, surfer litt rundt, for så å stoppe den. Da generer den et fiks ferdig ytelsestest-script for deg (riktignok med en del «ekstrastasj» du bør fjerne, f.eks alle sleep-kallene.)</li>
</ul>
<p style="text-align: right; font-size: 80%;">Bilder er fra stock.xchng, credit: <a href="http://www.sxc.hu/browse.phtml?f=download&amp;id=1242894">1</a>, <a href="http://www.sxc.hu/browse.phtml?f=download&amp;id=1319142">2</a>, <a href="http://www.sxc.hu/browse.phtml?f=download&amp;id=549019">3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/ytelsestesting-med-grinder/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Automated functional testing of iPhone apps with iCuke</title>
		<link>http://open.bekk.no/automated-functional-testing-of-iphone-apps-with-icuke/</link>
		<comments>http://open.bekk.no/automated-functional-testing-of-iphone-apps-with-icuke/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 12:05:20 +0000</pubDate>
		<dc:creator>Aslak Hellesøy</dc:creator>
				<category><![CDATA[Fri Programvare]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[icuke]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=2735</guid>
		<description><![CDATA[Seeing the downloads of the open source BDD/Acceptance Testing tool Cucumber skyrocketing is great, but seeing what insane extensions the community comes up with is even greater. UK-based super hacker and long time Cucumber contributor Rob Holland announced iCuke yesterday. iCuke is a Cucumber extension that lets you write automated functional tests for iPhone apps. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://open.bekk.no/wp-content/uploads/2010/06/icuke.png"><img class="size-full wp-image-2737 alignleft" title="icuke" src="http://open.bekk.no/wp-content/uploads/2010/06/icuke.png" alt="" width="110" height="203" /></a>Seeing the downloads of the open source BDD/Acceptance Testing tool Cucumber <a href="http://rubygems.org/gems/cucumber">skyrocketing</a> is great, but seeing what insane extensions the community comes up with is even greater.</p>
<p>UK-based super hacker and long time Cucumber contributor Rob Holland <a href="http://www.unboxedconsulting.com/blog/cucumber-iphone-icuke">announced iCuke yesterday</a>. iCuke is a Cucumber extension that lets you write automated functional tests for iPhone apps. Here is a little teaser&#8230;</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12230690&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12230690&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object>
<p><a href="http://vimeo.com/12230690">iCuke</a> from <a href="http://vimeo.com/user1178904">Aslak Hellesøy</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
<p>For questions about iCuke, please use the <a href="http://groups.google.com/group/icuke">iCuke mailing list</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/automated-functional-testing-of-iphone-apps-with-icuke/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Hva skjer når man gir bort flydata gratis?</title>
		<link>http://open.bekk.no/hva-skjer-nar-man-gir-bort-flydata-gratis/</link>
		<comments>http://open.bekk.no/hva-skjer-nar-man-gir-bort-flydata-gratis/#comments</comments>
		<pubDate>Sun, 13 Dec 2009 20:26:13 +0000</pubDate>
		<dc:creator>Anders Christensen</dc:creator>
				<category><![CDATA[IT-rådgivning]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Virksomhet 2.0]]></category>
		<category><![CDATA[åpne API]]></category>
		<category><![CDATA[Avinor]]></category>
		<category><![CDATA[gratis]]></category>
		<category><![CDATA[kvalitet]]></category>
		<category><![CDATA[omdømme]]></category>
		<category><![CDATA[open data]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=2123</guid>
		<description><![CDATA[Sommeren 2009 slapp Avinor (selskapet som eier og drifter landets 46 offentlige flyplasser) deler av sine flydata i XML-format til fri bruk for publikum. Erfaringene drøye 5 måneder etter frislippet er, ikke overraskende, positive.]]></description>
			<content:encoded><![CDATA[<h3><strong><span style="color: #000000;">Sommeren 2009 slapp <a title="avinor.no" href="http://www.avinor.no" target="_blank">Avinor</a> (selskapet som eier og drifter landets 46 offentlige flyplasser) deler av sine <a title="API for flydata fra Avinor" href="http://api.avinor.no" target="_blank">flydata i XML-format</a> til fri bruk for publikum. Erfaringene drøye 5 måneder etter frislippet er omtrent som følger:</span></strong></h3>
<p></br><br />
<strong>Erfaring 1: Gratis flydata bidrar til økt datakvalitet og tjenesteorientering</strong></p>
<p>Umiddelbart etter lanseringen kom kommentarene, spørsmålene og forslagene. Systemutviklere og <a title="flyspotter.net" href="http://www.flyspotter.net" target="_blank">flyspottere</a> tok raskt tak i tjenestene og meldte tilbake om inkonsistens og mangler i datasettene. Å bli utsatt for ”amatørers” (da i ordets <a title="Amatør - Wikipedia" href="http://no.wikipedia.org/wiki/Amat%C3%B8r" target="_blank">egentlige betydning</a>) nysgjerrige og kritiske blikk har vært en verdifull og nyttig erfaring for Avinor. Denne &#8220;kollektive kvalitetssikringen&#8221; har bidratt til å øke kvaliteten på de aktuelle datasettene.</p>
<p>En annen konsekvens av frislippet har vært en mer generell dreining i tankesettet internt i Avinor. At data som tidligere kun har vært i bruk internt nå er eksponert eksternt har økt fokuset på tjenesteorientering, samt bidratt til å tydeliggjøre ansvarsforholdet mellom ulike enheter i organisasjonen. Det oppleves nå som enklere å snakke om både bruk, gjenbruk og utvikling av tjenester.<br />
<br /></br><br />
<strong>Erfaring 2: Gratis flydata bidrar til &#8220;kollektiv innovasjon&#8221;</strong></p>
<div id="attachment_2175" class="wp-caption alignright" style="width: 330px"><strong><strong><img class="size-full wp-image-2175  " style="margin: 5px;" title="iphone_app" src="http://open.bekk.no/wp-content/uploads/2009/12/iphone_app.gif" alt="Eksempel på iPhone-app med flydata fra Avinor" width="320" height="213" /></strong></strong><p class="wp-caption-text">Eksempel på iPhone-app med flydata fra Avinor</p></div>
<p>Det er ikke bare Avinor som har hatt nytte av at flydataene nå er tilgjengelig eksternt. Publikum nyter også godt av frislippet.</p>
<p>Kort tid etter lanseringen dukket det opp løsninger som nå hjelper Avinor med å holde det reisende publikum oppdatert på flytrafikkavviklingen. I dag benyttes Avinors API til flere ulike applikasjoner på både iPhone- og Android-plattformen, samt tjenester på en rekke større norske nettsteder.</p>
<p>Dette var alle tjenester som Avinor selv gjerne ønsket å utvikle, men aldri hadde anledning til å prioritere. Men som antatt i forkant; slipper vi dataene fri så vil andre lage løsningene &#8220;for oss&#8221;. Resultatet blir det samme; folk får tilgang til flytider.</p>
<p>(Som motvekt til iPhone-hysteriet utviklet forøvrig Avinor selv en <a title="Flytider på mobilen" href="http://m.osl.no" target="_blank">enkel webløsning</a> som fungerer på alle mobiltelefoner.)<br />
<br /></br><br />
<strong>Erfaring 3: Gratis flydata er positivt for omdømmet til Avinor</strong></p>
<p>Lanseringen av API&#8217;et har bidratt til at Avinor ved flere anledninger har fått positiv medieomtale. De siste månedene har blant annet <a title="nrkbeta.no" href="http://nrkbeta.no/2009/07/02/gratis-flydata-fra-avinor/" target="_blank">NRKbeta</a>, <a title="Dagbladet.no" href="http://www.dagbladet.no/2009/11/12/kultur/tekno/data_og_teknologi/statens_kartverk/9003977/" target="_blank">Dagbladet.no</a> og <a title="tu.no" href="http://www.tu.no/it/article216246.ece" target="_blank">Teknisk Ukeblad</a> hatt oppslag hvor Avinor trekkes fram som eksempel til etterfølgelse. Rett nok har omtalen vært relativt ”smal”, men all positiv omtale er eh… positivt (særlig når man tar i betraktning at Avinor stort sett bare er interessant for mediene når ting <em>ikke</em> går på skinner).</p>
<p>Internt har lanseringen også hatt en positiv omdømmeeffekt. Open data både <em>føles</em> og <em>er</em> moderne. Og Avinor har vært relativt tidlig ute på dette området. Per i dag har ikke altfor mange statlige virksomheter sluppet sine data til fri bruk, og innen internasjonal flytrafikk er eksemplene enda færre. Tanken på det kan gjøre en og annen ansatt i Avinor stolt. Open data bør definitivt være en målsetning, men foreløpig er det ingen selvfølge. Kudos til de som går foran.</p>
<p>- &#8211; - &#8211; -</p>
<p><em>Kommentar: Betydningen av erfaring 3 skal ikke overdrives. Verdien av erfaring 1 og 2 skal derimot ikke underdrives. Undertegnede er forøvrig en av flere BEKKere som jobber for Avinor. </em><br />
<br /></br></p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/hva-skjer-nar-man-gir-bort-flydata-gratis/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Javadocstøy #2</title>
		<link>http://open.bekk.no/javadocst%c3%b8y-2/</link>
		<comments>http://open.bekk.no/javadocst%c3%b8y-2/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 14:24:18 +0000</pubDate>
		<dc:creator>Trond Arve Wasskog</dc:creator>
				<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[dokumentasjon]]></category>
		<category><![CDATA[håndtverk]]></category>
		<category><![CDATA[javadoc]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1998</guid>
		<description><![CDATA[Noen spør hvorfor jeg bruker energi på Javadocstøy. Finnes det ikke større fisker å steke?]]></description>
			<content:encoded><![CDATA[<p>Noen spør hvorfor jeg bruker energi på <a title="Javadocstøy #fail" href="http://open.bekk.no/2009/11/27/javadocst%c3%b8y/">Javadocstøy</a>. Finnes det ikke større fisker å steke?</p>
<p>Årsaken er at det indikerer at man har <em>sluttet å engasjere seg</em>. Man godtar ubrukelige regler, på tross av utvilsom støyfaktor og null verdi. Det tyder på at man ikke bryr seg om koden sin. Og kode er det mest sentrale vi produserer, kommuniserer og vedlikeholder.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/javadocst%c3%b8y-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riktig feilhåndtering: Kontekstinformasjon</title>
		<link>http://open.bekk.no/riktig-feilhandtering-kontekstinformasjon/</link>
		<comments>http://open.bekk.no/riktig-feilhandtering-kontekstinformasjon/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 07:17:10 +0000</pubDate>
		<dc:creator>Trond Arve Wasskog</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1687</guid>
		<description><![CDATA[For å feilsøke og finne årsaken til en feil har man behov for informasjon om kontekst når situasjonen inntraff. Dette inkluderer overordnet informasjon som maskin, bruker, tidspunkt og opprinnelse i koden. I tillegg vil man gjerne ha spesifikk informasjon om tilstand og data som ble behandlet. Målet er å kunne gjenskape situasjonen i et utviklingsmiljø for å forstå og rette feilen.]]></description>
			<content:encoded><![CDATA[<p>For å feilsøke og finne årsaken til en feil har man behov for informasjon om kontekst når situasjonen inntraff. Dette inkluderer overordnet informasjon som maskin, bruker, tidspunkt og opprinnelse i koden. I tillegg vil man gjerne ha spesifikk informasjon om tilstand og data som ble behandlet. Målet er å kunne gjenskape situasjonen i et utviklingsmiljø for å forstå og rette feilen.</p>
<p><strong>Standard informasjon</strong></p>
<p>Standard logginformasjon inkluderer typisk tidspunkt, alvorlighetsgrad, program- og komponentnavn i tillegg til selve meldingen. Et godt loggrammeverk tilbyr tilpasning av både innhold og format av disse parametrene.</p>
<p>Riktig feilhåndtering forutsetter fornuftig <a title="Feilkategoriseing og -hendelse" href="http://open.bekk.no/2009/11/18/riktig-feilhandtering-feilkategori-og-hendelse/">kategorisering og identifisering av feilhendelse.</a> Feilkategori og unik feil-ID er en viktig del av kontekstinformasjonen.</p>
<p><strong>Brukernavn</strong></p>
<p>Brukernavn for den innloggede brukeren kan med fordel logges. Enkelte applikasjonsservere tilbyr denne funksjonaliteten forutsatt at du benytter de innebygde mekanismene for autentisering og logging. En teknikk man kan benytte i egen kode er å ha brukernavnet på trådkonteksten (for eksempel  en <a title="Java ThreadLocal" href="http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html">ThreadLocal</a> variabel i Java). Når en feil oppstår henter loggmekanismen brukernavnet fra trådkonteksten og skriver det til loggen. Mange sikkerhetsrammeverk bruker også denne teknikken, det kan derfor hende at brukernavnet allerede ligger klart for bruk.</p>
<p><strong>Støtte for vilkårlig kontekstinformasjon</strong></p>
<p>Når en feil oppstår er det gjerne nyttig å legge til spesifikk informasjon om tilstand og kontekst. Det kan også være behov for å supplere mer informasjon oppover i kall-stacken. Rammeverket bør derfor ha støtte for å legge til vilkårlig kontekstinformasjon, for eksempel som skissert under.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   ...
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> leggTilFeilinformasjon<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> navn, <span style="color: #003399;">Object</span> info<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      feilinformasjon.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>navn, info<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Selvbeskrivende objekter</strong></p>
<p>Når man skal logge tilstand for de ulike objektene er det en stor fordel at disse kan beskrive seg selv. Det er feil ansvarsfordeling dersom en feilhåndteringsrutine må pakke ut og formattere kontekstinformasjonen som skal logges. En slik tilnærming vil også sannsynligvis føre til inkonsistens og duplisering.</p>
<p>Java-mekanismen for selvbeskrivende objekter er den velkjente <a href="http://www.j2ee.me/javase/6/docs/api/java/lang/Object.html#toString%28%29">toString()-metoden</a>. Ved å implementere toString() på en god måte vil tilstand kunne logges enkelt og konsistent. I tillegg er det enkelt å lage automatiserte tester for denne funksjonaliteten, og disse kan også fungere som dokumentasjon. Komponenter som <a href="http://commons.apache.org/lang/api/org/apache/commons/lang/builder/ToStringBuilder.html">Apache ToStringBuilder</a> kan være nyttig for implementasjon av toString().</p>
<p><strong>Stacktrace og uventede feil<br />
</strong></p>
<p>God feilhåndtering<a href="http://open.bekk.no/2009/11/02/riktig-feilhandtering-det-finnes-bare-tre-feiltyper/"> betyr få stacktrace i loggen</a>. Ideelt sett oppstår behovet for stacktrace kun ved programmeringsfeil; gitt at applikasjonsfeil og systemfeil er riktig håndtert og har tilstrekkelig kontekstinformasjon. Imidlertid, når en uventet feil først oppstår er stacktracen en uvurderlig del av kontekstinformasjonen. Man kan med forlel skille ut disse i en egen logg for utviklere; drift ser ofte på stacktrace som et verdiløst irritasjonsmoment.</p>
<p><strong>Oppsummering</strong></p>
<p>God kontekstinformasjon er en sentral mekanisme for riktig feilhåndtering. Drift og utvikling kan med stor sannsynlighet forstå og gjenskape feilsituasjonen, og dermed også rette feilen raskt. Teknikkene for kontekstinformasjon er enkle å implementere, forutsatt at feilhåndtering er en prioritert og forstått del av prosjektet.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/riktig-feilhandtering-kontekstinformasjon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riktig feilhåndtering: Hvem bryr seg?</title>
		<link>http://open.bekk.no/riktig-feilhandtering-hvem-bryr-seg/</link>
		<comments>http://open.bekk.no/riktig-feilhandtering-hvem-bryr-seg/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 19:23:58 +0000</pubDate>
		<dc:creator>Trond Arve Wasskog</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1662</guid>
		<description><![CDATA[For bedre feilhåndtering må man i større grad skille mellom ulike brukergrupper og deres behov.]]></description>
			<content:encoded><![CDATA[<p>Å kjenne brukerne og deres behov er sentralt i all utvikling. Dette gjelder også feilhåndtering. Her er en oversikt over typiske brukergrupper og deres behov:<em> </em></p>
<p><strong>Brukeren</strong></p>
<p>Brukeren av systemet er først og fremst opptatt av <em>at </em>en feil har oppstått, at situasjonen er håndtert og ikke medfører senere problemer. Det er selvfølgelig irriterende og kan være problematisk når feil inntreffer, uansett er det kritisk at situasjonen ser ut til å være under kontroll. Brukeren bryr seg sjelden om årsaken til feilen, men vil gjerne kunne identifisere den spesifikke situasjonen når hun snakker med supportapparatet.</p>
<p><strong>Forretningssiden</strong></p>
<p>Forretningssiden (funksjonelt ansvarlige i utviklingsprosessen) forstår primært funksjonelle feil, og antar ofte at utviklere og leverandører tar seg av andre feiltyper. De ønsker generelt en applikasjon uten kritiske feil, men vil sjelden sørge for at feilhåndtering blir riktig prioritert i utviklingsprosessen.</p>
<p><strong>Kunde/Bestiller</strong></p>
<p>Den som sitter på budsjettet og bestiller applikasjonen har forventninger om en fungerende applikasjon, men har vent seg til at ingen applikasjoner er feilfrie. De er vanligvis ikke tilstrekkelig involvert i prosjektet til å påvirke og vektlegge feilhåndtering. Noen stiller imidlertid med testledere som kan være erfarne nok til å ivareta dette ansvaret og sørge for at unntaks- og feilsituasjoner blir testet.</p>
<p><strong>Drift</strong></p>
<p>Drift vil vite <em>hva de skal gjøre når feil oppstår</em>. På kort sikt er drift kun interessert i å gjøre grep slik at systemet kjører videre og ikke har havnet i en ugyldig tilstand. Selv om årsaken til feilen kan være interessant vil driftpersoner sjelden ha behov for detaljerte beskrivelser. Imidlertid vil de gjerne ha en oversikt over potensielle og kjente feilsituasjoner, kunne gjenkjenne feilkategoriene og kanskje bygge opp en erfaringsbase  over tid.</p>
<p><strong>Utviklere</strong></p>
<p>Utviklere vil vite <em>alt</em>:</p>
<ul>
<li>Hva var årsaken til feilen?</li>
<li>På hvilken server skjedde den?</li>
<li>Når oppsto situasjonen?</li>
<li>Hvilken tilstand hadde brukeren og applikasjonen?</li>
<li>Hva var kontekst i feilsituasjonen?</li>
<li>Kan den gjenskapes?</li>
</ul>
<p>Ettersom utviklere ofte står for feilhåndteringen vil utviklerbehovene prege implementasjonen. Dette resulterer gjerne i detaljerte feilmeldinger i alle sammenhenger; i brukergrensesnittet, loggfiler og konsoller.</p>
<p><strong>Tilpasning til brukernes behov</strong></p>
<p>For bedre feilhåndtering må man i større grad skille mellom ulike brukergrupper og deres behov. Her er noen mulige tilnærminger:</p>
<ul>
<li>Utviklingsprosjektet må ta hovedansvaret for feilhåndteringen. All erfaring tilsier at man ikke kan forvente at forretningssiden eller bestiller vil sørge for at behovene beskrives og prioriteres. Dersom kunden ikke har en erfaren testleder bør prosjektene selv bekle denne rollen.</li>
<li>Unngå detaljerte feilbeskrivelser i brukergrensesnittet, men oppgi gjerne en unik feil-ID slik at det er mulig å finne tilbake til den spesifikke feilen.</li>
<li>Involver drift i hele utviklingsprosjektet slik at de kan bidra til kravstilling og kommunisere sine behov på lik linje med funksjonelle krav.</li>
<li>Sørg for konsistent feilkategorisering som drift kan bruke for å kjenne igjen feil.</li>
<li>Bruk gjerne forskjellige logger for drift og feilretting. Drift har i utgangspunktet ikke behov for de detaljerte feilbeskrivelsene som man har i forvaltning.</li>
<li>Sørg for å legge til kontekstinformasjon i feilsituasjoner.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/riktig-feilhandtering-hvem-bryr-seg/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Riktig feilhåndtering: Feilkategori og -hendelse</title>
		<link>http://open.bekk.no/riktig-feilhandtering-feilkategori-og-hendelse/</link>
		<comments>http://open.bekk.no/riktig-feilhandtering-feilkategori-og-hendelse/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:19:14 +0000</pubDate>
		<dc:creator>Trond Arve Wasskog</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1560</guid>
		<description><![CDATA[Når man feilsøker kan man skille mellom feilkategori og feilhendelse. Kategorien beskriver hvilken feiltype som har oppstått, mens identifisering av feilhendelsen forteller hva som har skjedd til en bestemt tid i en spesifikk sammenheng.]]></description>
			<content:encoded><![CDATA[<p><strong>Feilkategori vs. -hendelse</strong></p>
<p>Når man feilsøker kan man skille mellom to ulike behov:</p>
<ul>
<li><em>Feilkategori</em> beskriver hvilken feil som har oppstått. Den kategoriserer hendelser av samme type, og brukes for å forstå hva som har skjedd.</li>
<li>Identifisering av <em>feilhendelsen</em> forteller hva som har skjedd til en bestemt tid i en spesifikk sammenheng. Typisk er dette nyttig for å finne ut hva som har skjedd når man feilsøker en bestemt feilsituasjon meldt av en bruker.</li>
</ul>
<p><strong>Feilkategorisering</strong></p>
<p>Feilkategorisering har flere alternative tilnærminger:</p>
<ul>
<li>Hver feilkategori representeres med en egen Exception. <a title="java.lang.Exception" href="http://java.sun.com/javase/6/docs/api/java/lang/Exception.html" target="_blank">Java SE APIet</a> er et eksempel på denne tilnærmingen. Dette resulterer typisk i mange Exception-klasser  definert på ulike steder i pakkestrukturen. Tilnærmingen kan derfor kalles <em>distribuert</em>.</li>
<li>Et fåtall sentrale Exception-klasser definerer feiltypene (gjerne <a title="Tre feiltyper" href="http://open.bekk.no/2009/11/02/riktig-feilhandtering-det-finnes-bare-tre-feiltyper/">Applikasjonsfeil, Systemfeil og Programmeringsfeil</a>). For hver feiltype defineres en ID som feiltypen bærer med seg (typisk en Enum spesifisert i constructor). Denne tilnærmingen kan ses på som <em>sentralisert</em>.</li>
<li>Kombinasjoner av disse, for eksempel et fåtall sentrale Exception-klasser med distribuerte subklasser.</li>
</ul>
<div style="text-align: center;"><img style="border: 1px solid black;" title="Sentralisert feilhierarki" src="http://open.bekk.no/wp-content/uploads/2009/11/SentralisertFeilhierarki.png" alt="Sentralisert feilhierarki" /><br />
<em>Sentralisert feilhierarki</em></div>
<p>Uavhengig av tilnærming er hensikten å gjenkjenne feilen og forstå hvorfor den oppstår. En driftsperson vil kanskje lage en erfaringsbase for kjente feilkategorier. En utvikler som skal feilrette har også god nytte av god feilkategorisering for å finne årsaken.</p>
<p>Min erfaring er at applikasjoner lykkes best med en sentralisert tilnærming, der man definerer feilkategoriene som en felles Enum. Rammeverk (f.eks. Java SE API og Spring Framework) velger gjerne en distribuert tilnærming; ettersom dette ikke er applikasjoner har man ikke det samme behovet for sentral oversikt over feilkategoriene.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">Enum</span> Kategori <span style="color: #009900;">&#123;</span> INGEN_PENGER, FEIL_ROLLE, UTESTENGT <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
...
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">public</span> AbstractException<span style="color: #009900;">&#40;</span>Kategori kategori, ...<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      ...
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: center;"><em>Kategorisereing av feil ved hjelp av Enum</em></p>
<p><strong>Identifisering av feilhendelse</strong></p>
<p>For å finne ut av en spesifikk feil ønsker man å identifisere den unike hendelsen som forårsaket feilen. Typisk er dette en situasjon der en bruker melder en feil eller når man feilsøker en hendelse som andre har rapportert tidligere. Å kunne identifisere denne ene feilen i en stor loggfil er gull verdt. Dette krever at hver enkelt feil blir logget med en unik ID.</p>
<p>En teknikk som fungerer bra nok i de fleste sammenhenger er å bruke tidspunktet feilen oppstår (i millisekunder) som ID. Denne IDen vises i feilsammenheng og skrives samtidig til feilloggen. Sannsynligheten for at to eller flere feil oppstår i samme millisekund er tilstede, men denne teknikken vil uansett begrense utvalget til et minimum. Funksjonaliteten for å lagre IDen implementeres i Exception-superklassen.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AbstractException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">long</span> uid<span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">public</span> AbstractException<span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      uid <span style="color: #339933;">=</span> <span style="color: #003399;">System</span>.<span style="color: #006633;">currentTimeMillis</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// skrives til loggen</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p style="text-align: center;"><em>Eksempel på identifisering av Exception-instans med timestamp.</em></p>
<p><strong>Oppsummering</strong></p>
<p>God feilhåndtering forutsetter riktig kategorisering av feil i tillegg til støtte for å identifisere hver enkelt feilhendelse. Som alltid krever dette at man har et bevisst og målrettet forhold til feilhåndtering gjennom hele prosjektløpet. Det er fullt mulig å unngå at feilkategorisering og idendifisering av feilhendelse blir klattet på mot slutten av et prosjekt; å involvere driftpersoner som kravstillere på lik linje med annen funksjonalitet er en god start. God kontekstinformasjon i en feilsituasjon er også viktig, dette blir et eget tema i denne serien.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/riktig-feilhandtering-feilkategori-og-hendelse/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Riktig feilhåndtering: Det finnes bare tre feiltyper</title>
		<link>http://open.bekk.no/riktig-feilhandtering-det-finnes-bare-tre-feiltyper/</link>
		<comments>http://open.bekk.no/riktig-feilhandtering-det-finnes-bare-tre-feiltyper/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 19:24:47 +0000</pubDate>
		<dc:creator>Trond Arve Wasskog</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[driftbarhet]]></category>
		<category><![CDATA[feilhåndtering]]></category>
		<category><![CDATA[kvalitet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1484</guid>
		<description><![CDATA[Det finnes bare tre feiltyper: Applikasjonsfeil, Systemfeil og Programmeringsfeil. 
]]></description>
			<content:encoded><![CDATA[<p>I en applikasjon finnes det bare typer feil:</p>
<ul>
<li>Applikasjonsfeil</li>
<li>Systemfeil</li>
<li>Programmeringsfeil</li>
</ul>
<p>Applikasjonsfeil skyldes at funksjonelle forutsetninger ikke er tilfredsstilt. I praksis er dette gjerne ugyldig eller feilformatert input som for kort fødselsnummer, e-postadresse uten @, dobbeltføring av betaling eller en kunde som har utilstrekkelig bonusnivå for å utføre en handling. Applikasjonsfeil kan sies å være forventet og skal håndteres på lik linje med andre krav. Det kan være krevende å forutse alle slike feilsituasjoner. Erfaringsmessig har forretningsfolk god oversikt over de vanligste funksjonelle problemene, mens teknikere er flinke til å tenke på grenseverdier og inkonsistens. En iterativ tilnærming med teknikker som test-drevet utvikling, brukerhistorier og BDD vil avsløre de fleste applikasjonsfeilene. I utgangspunktet skal det ikke være nødvendig å feilrette og rulle ut en ny versjon av applikasjonen for denne typen feil. For å håndtere applikasjonsfeilene som allikevel slipper ut i produksjon er det viktig med hyppig utrulling slik at man kan fange opp disse etterhvert som man får praktisk erfaring med systemet.</p>
<p>Systemfeil skyldes feil i applikasjonens omgivelser eller infrastruktur. Typisk er dette en disk som går full, et nettverk som blir utilgjengelig eller en server blir overbelastet. Slike feil er også til en viss grad forventet; de opptrer sjelden, kan være vanskelig å forutse, men i praksis er det gjerne rimelig enkelt å teste slike feilsituasjoner. Ved systemfeil kan det gi mening å kjøre <em>fail-over</em> om mulig, alternativt vente en stund for deretter å prøve operasjonen på nytt; denne type feilhåndtering tilbys gjerne av meldingssystemer. Feilretting og ny utrulling skal ikke være nødvendig for denne feiltypen.</p>
<p>Programmeringsfeil skyldes at utviklere ikke har gjort jobben sin. De oppstår når applikasjonen ikke klarer å håndtere uventede hendelser på på robust vis. Typiske eksempler på dette (i en Java-applikasjon) er når systemet spyr ut feil av typen NullPointerException, NoSuchElementException og IndexOutOfBoundsException. Godt håndtverk med teknikker som TDD og automatisert testing, parprogrammering og kodegjennomgang er effektive tilnærminger for å minimere denne typen feil. Når en programmeringsfeil oppstår krever det en feilretting og påfølgende utrulling av ny versjon.</p>
<p>Tabellen under gir en oversikt over feiltypene og om de bør fanges og håndteres i applikasjonen, om det er mulig å vente litt og prøve operasjonen på nytt samt om den krever feilretting og utrulling av ny versjon:</p>
<table border="1" align="center">
<tbody>
<tr>
<th>Type</th>
<th>Fanges og håndteres?</th>
<th>Prøve på nytt?</th>
<th>Feilretting og utrulling?</th>
</tr>
<tr style="text-align: center;">
<td>Applikasjonsfeil</td>
<td>Ja/Mulig</td>
<td>Nei</td>
<td>Nei</td>
</tr>
<tr style="text-align: center;">
<td>Systemfeil</td>
<td>Nei/Mulig</td>
<td>Ja</td>
<td>Nei</td>
</tr>
<tr style="text-align: center;">
<td>Programmeringsfeil</td>
<td>Nei</td>
<td>Nei</td>
<td>Ja</td>
</tr>
</tbody>
</table>
<p>Dårlig feilhåndtering er dessverre alt for utbredt i vår industri. Antall stacktrace i loggen er en indikator på hvilken kvalitet applikasjonen har; applikasjonsfeil og systemfeil skal være håndtert mens programmeringsfeil skal være luket ut i utviklingsprosessen. Et bevisst forhold til feiltyper og hvordan de bør håndteres er et godt utgangspunkt for å lykkes på dette området. Riktig feilhåndtering krever imidlertid målrettet innsats gjennom hele utviklingsløpet.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/riktig-feilhandtering-det-finnes-bare-tre-feiltyper/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tekniske renter &#8211; en annen måte å måle teknisk gjeld på.</title>
		<link>http://open.bekk.no/tekniske-renter-en-annen-mate-a-male-teknisk-gjeld-pa/</link>
		<comments>http://open.bekk.no/tekniske-renter-en-annen-mate-a-male-teknisk-gjeld-pa/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 14:47:52 +0000</pubDate>
		<dc:creator>Aslak Johannessen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[forvaltning]]></category>
		<category><![CDATA[kontinuerlig forbedring]]></category>
		<category><![CDATA[teknisk gjeld]]></category>
		<category><![CDATA[tekniske renter]]></category>
		<category><![CDATA[utviklingshastighet]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1473</guid>
		<description><![CDATA[Teknisk gjeld er et velkjent begrep for de fleste og brukes ofte som en betegnelse på hvor god helse koden har. Begrepet peker på de delene av en kodebase som ikke er av god kvalitet. Hensikten med å klassifisere disse delene er selvfølgelig at man senere skal komme tilbake å fikse opp i ugjerningen. Den [...]]]></description>
			<content:encoded><![CDATA[<h3>Teknisk gjeld er et velkjent <a href="http://en.wikipedia.org/wiki/Technical_debt">begrep</a> for de fleste og brukes ofte som en betegnelse på hvor god helse koden har. Begrepet peker på de delene av en kodebase som ikke er av god kvalitet. Hensikten med å klassifisere disse delene er selvfølgelig at man senere skal komme tilbake å fikse opp i ugjerningen. Den klassiske måten å måle teknisk gjeld på er å lage en liste med punkter over kjent gjeld, for deretter å telle antall punkter på listen.</h3>
<p>Hvis man tar innover seg gjeldsbegrepet så er det i praksis ikke gjelden, men rentene som kjennes på kroppen. Vi mener at det er mer hensiktsmessig å måle tekniske renter enn teknisk gjeld. Rentene kan man enkelt finne ved å se på differansen mellom hvor lang tid det tar å implementere en oppgave i et nyoppstartet utviklingsprosjekt i forhold til i forvaltning. Hvis man bruker 1 time på å lage en avkryssningsboks i nyutvikling og 8 timer i forvaltning, kan man regne med at 7 av disse timene er renter. Hastigheten man en gang hadde er nå redusert, differansen velger vi å se på som tekniske renter. Dette er tid som er lite nyttig og oppleves som frustrerende, tid som vi gjerne ønsker å bruke til noe annet.</p>
<p>I BEKK forvaltning har vi mange prosjekter med en hel del nedskrevet og noe glemt gjeld. Vi har undersøkt om vi kan måle de tekniske rentene på denne gjelden og om dette kan gi oss et bedre bilde av hvilke utfordringer vi står ovenfor. Målet er å kunne gjøre forvaltning av applikasjoner på en bedre måte.</p>
<p>Ved å notere når man betaler tekniske renter fant vi raskt ut hvilken størrelseorden gjelden var på. Samtidig ser vi i hvilken del av applikasjonen gjelden befinner seg. Delen med gjeld er den delen av systemet man jobber med når rentene betales. Grafen under viser hvordan vi ser for oss en slik rentebetaling gjennom utviklingsløpet. Hastigheten eller &#8220;Valuta for pengene&#8221; på y-aksen og tid langs x-aksen.</p>
<div id="gx1n" style="text-align: left;">
<div style="text-align: center;"><img style="width: 648px; height: 415.396px;" src="http://docs.google.com/File?id=dhmkvkzc_162ttbcszp_b" alt="" /></div>
<p>De faktorene vi har tatt for oss vil hver for seg senke utviklingshastigheten. Hver av faktorene peker på et området hvor vi betaler renter og derfor har teknisk gjeld. Det finnes mange flere punkter og de varierer selvfølgelig fra prosjekt til prosjekt. Dette er vår liste, du kan sikkert finne flere punkter vi hadde satt pris på om du legger de til i kommentarfeltet.</p>
<p>Figuren over viser at hvis man for eksempel mister fokus på å skape verdi så vil hastigheten synke over tid. Hvis man i tillegg mister overføring av kompetanse vil utviklingshastigheten reduseres ytligere på grunn av manglende kompetanse hos de som skal gjøre jobben framover. Konsekvensen av de ulike punktene akkumulerer slik at de totalt bidrar til en reduksjon av utviklingshastigheten.</p>
<p><em>Verdifokus</em><br />
Prosjekter som har gått lenge har ofte en tendens til å bli preget av at prosjektet i bunn og grunn består i å rette feil. Det har tapt verdifokus i og med at man jobber med ting som ikke nødvendigvis gir mest verdi for pengene. I disse situasjonene har man ofte mistet overblikket og retningen for hvorfor prosjektet er i drift. Samtidig som koden man skriver blir vanskelig å vedlikeholde når de store linjene ikke tydelig kommer fram.</p>
<p><em>Kompetanse</em><br />
Ofte ser vi prosjekter som sprinter mot lansering og i det prosjektet er ferdig går hele teamet over på nye prosjekter. Med de forsvinner også viktig kunnskap. Vi ser at ved å overlappe forvaltningsteamet med utviklingsteamet (dette kan gjøres på mange måter) slipper vi å gjenoppdage rutiner og konvensjoner. Tid man kan bruke på viktigere ting.</p>
<p><em>Automatiserte tester</em><br />
Prosjekter av en viss alder har ikke automatiserte tester, eller tester i det hele tatt. Renter blir her betalt ved å opprette tester og regresjonstester for de delene av systemet hvor man skal gjøre endringer. Det å få tilbakebetalt disse rentene kan ta mye tid, men vi obsererer gang på gang at det er helt essensielt for at utviklinghastigheten skal øke.</p>
<p><em>Byggerutiner</em><br />
Hvis noe gjør vondt, gjør det ofte. Hvis du gjør noe ofte, automatiser det. Det sier seg selv at slike oppgaver er repetitive, og hvis du gjør dem ofte tar de mye tid. Som igjen gjør at du bruker mye tid på å gjøre disse oppgavene.</p>
<p><em>Historie</em><br />
Vi har i noen prosjekter brukt mye tid på å finne bakgrunnen for en designavgjørelse. I andre prosjekter har dette vært dokumentert ved god og uttrykksfull kode eller i form av en god og forståelig commit melding. Dette er steder hvor informasjonen er knyttet til kontekst (revisjon eller integrasjonspunkter) og hvis integrasjonspunktet endrer seg vil man med større sannsynlighet slette koden, i motsetning til dokumentet som omhandler det.</p>
<p>Hvert av punktene beskriver hvordan vi identifiserer at vi betaler renter og hvordan vi løste våre problemer. Det vi ønsker å få fram er ikke nødvendigvis størrelsen på den tekniske gjelden men hvordan man identifiserer den ved å se på betaling av renter. Ved å identifisere det vil man også være i en bedre posisjon for å ta problemet ved roten.</p>
<h4>Konsekvensene ved å ta opp teknisk gjeld er ikke nødvendigvis gjelden i seg selv, men rentene du betaler på den. Dette viser seg i den ekstra tiden du bruker på oppgaver som gikk raskere før. Gjelden må håndteres for at utviklingshastigheten ikke skal bremse opp. Det koster dine kunder mye, og gir deg kjedelige oppgaver.</h4>
</div>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/tekniske-renter-en-annen-mate-a-male-teknisk-gjeld-pa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

