Tag: tdd

Presentation om testdriven JavaScript-utveckling

Igår talade jag på JavaForum om tre verktyg (JsTestDriver, JsHamcrest, JsMockito) som möjliggör en godkänt komfortabel miljö för testdriven utveckling av JavaScript-kod. Jag har slangat upp presentationen på SlideShare och koden som det refereras till finns på GitHub.

Jag skulle kanske tryckt lite mer på att det i min mening inte lämpar sig för end-to-end-tester, typ ATDD eller BDD – där är fortfarande något som har Selenium i botten kung (om man gör det rätt).

Kata: Authentication Filter in Java EE

This is an exercise I’ve used to demonstrate how awkward unit testing can be if you can’t use a mocking framework. It’s an almost real work life situation (disclaimer: you should perhaps use container based authentication and JAAS) where we’re using API:s in a Java EE Server, adding two collaborators and then writing the logic combining it all.

No group has (yet) completed the entire task within 90 minutes – you might want to start/focus on using one collaborator only (I suggest the LDAP collaborator).

Originally posted on codingdojo.org.

When cleaning up a folder at work, I found this old document – it’s some form of a logical flow chart of the filter to write.

Here we go …

Background

In this Kata, your a programmer at ABC Corp and you’re making a new web app from scratch. After the head architect started working on this, it’s now up to you to make sure these tasks are completed:

  • allow authentication using request parameters
  • all authentication/login attempts should be verified agains LDAP
  • successful logins should be recorded in the single sign on registry

However, you’re not the only programmer (team) adressing this web app, so the LDAP is written by another team and what you have right now is this interface:

 public interface LdapAuthenticationGateway {
   boolean credentialsAreValid(String userName, String password);
 }

and the single sign on registry is also written by another team, leaving you with this interface:

 public interface SingleSignOnRegistry {
   boolean tokenIsValid(String token);
   String registerNewSession(String userName);
   void endSession(String token);
 }

Your job basically is to write one or more javax.servlet.Filter that handles incoming requests and act according to whether there’s a cookie with a SSO token, username+password parameters etc.

It’s assumed that there’s some form of DependencyInjection framework in place – to get a handle to the SingleSignOnRegistry or the LdapAuthenticationGateway, you’ll simply have to provide something like:

 public void setSingleSignOnRegistry(SingleSignOnRegistry registry) {
   ...
 }

About this kata

This “real life” scenario has been used to demonstrate how mocking (using Mockito) can be useful. We’ve combined it with BDD and JDojo@Gbg will try to practice TDD using this kata (without mocking) next time around.

(“Real life” is quoted – proper JEE authentication should be tied into the container etc etc … The point with this exercise is that it’s fairly easy to explain how it should work and what needs to be done here with “real” Java EE API:s, and then focus on the “How to develop” aspect (TDD), but also to show/talk about the difference between mocking and stubbing.)

JsTestDriver

Most of my code writing time last week writing was spent in JavaScript land (or ECMAScript, wonder it the most commonly used name will ever change). I was to write a small templating package and had to write some new stuff and set out to use JsTestDriver and after a few minutes I was up and running in Eclipse.

The idea is OK I guess – run tests and production code in the same environment it will run in when deployed. There are a couple of cons to JsTestDriver (used through Eclipse) though:

  1. if you’re configuration file doesn’t include the test file you’re trying to execute, there’s no clue to what you’ve done wrong – the panel in Eclipse will just show the green bar and 0/0 tests run.
  2. if you have syntax (or construct like) errors in your unit under test, you’ll get the same behavior as above
  3. sometimes you’re served a cached version of (some of) the JS source files – hence there’s a button to “refresh browsers” and it’s sad that it has to be there and that you actually have to use it
  4. sometimes the engine gets into some strange state where it dryRuns the tests instead of actually executing them

Apart from that, its behavior is quite predictable. Minor issues:

  1. running a test complete locks Eclipse’s UI thread
  2. a Rerun quick command option would be great (Ctrl+3)

JsHamcrest

Another minor issue is that the “index” of JsHamcrest matchers is really hard to get an overview of. Whenever I wanted to use a certain type of matcher, it was really hard to quickly tell from the documentation if it was there or not. Go see for yourself and look for a matcher that mathes any object for instance.

JsHamcrest.Integration.JsTestDriver();
# get a list of matchers:
curl "http://jshamcrest.destaquenet.com/modules/matchers.html" | grep "dt id" |cut -d '"' -f 2 |cut -d '.' -f 3

JsMockito

JsMockito works really nice. The only thing that could’ve been better is the integration with JsTestDriver: when a verify step fails, you’ll get a good error message but you don’t get the typical feedback as from which line the verify/assert that failed was on. Not a big deal since you see which test that failed.

JsMockito.Integration.JsTestDriver();

Böcker om Scrum mm

Jag brukar ta med mig ett par böcker när jag håller workshops eller predikar om ett ämne jag håller nära hjärtat. Eftersom det ofta är svårt att hinna svara alla frågor eller gå på djupet på alla ämnen så brukar det uppskattas att jag lämnar referenser till böcker (eller bloggar) där man kan gräva sig djupare. Efter fredagens “Agile Injection” fick jag frågan om att skicka över listan med böcker jag hade med mig då. Här är den. :)

Följande utmärkta böcker rekomenderas varmt

Agile Project Managemeng with Scrum, Ken Schwaber
9780735619937
Appendix A är Scrum i ett nötskal (~10 sidor). “A book of case studies about Scrum”. Som Knibergs bok, fast mer polerad och mindre detaljrik.

Scrum and XP from the Trenches, Henrik Kniberg
9781430322641
125 sidor med erfarenheter: how we do testing, how we do sprint backlog, how we arrange the team room, how we do daily scrums, … Man bör kunna grunderna (helst prövat på) för att fullt uppskatta boken.

Clean Code, Robert C. Martin
9780132350884
Utmärkt genomgång av hur man renskriver kod, och varför. Ögonöppnare för många.

Working Effectively with Legacy Code, Michael C. Feathers
9780131177055
Utmärkt bok om “refactoring” – hur skall man attackera legacy code (dvs kod som inte täcks av automattest).

Mycket bra är också

The Pragmatic Programmer, Andrew Hunt, David Thomas
9780201616224
Insiktsfullt om kärnan av systemutveckling – hur jobbar en “bra” utvecklare (eller hur blir man).

Följande böcker har inte samma nivå, men är fortfarande bra.

Extreme Programming Explained, Second Ed, Kent Beck, Cynthia Andres
0321278658
Kent Beck försöker förklara Extreme Programming. Lyckas sådär.

Test-Driven Development, Kent Beck
9780321146533
Kent Beck visar upp TDD i praktiken med riktig kod i tre kapitel. En bra praktisk genomgång.

Andra har uppskattat

User Stories Applied, Mike Cohn
Agile Estimating and Planning, Mike Cohn
Agile Software Development with Scrum, Schwaber, Beedle

och lite utanför ämnet

The Mythical Man-Month, Frederick P. Brooks, JR
9780201835953
Insikter kring mjukvaruutvecklingen från 1975, med uppdatering tjugo år senare. Intressant om man tycker utveckling av systemutveckling över tiden är intressant.

Ämnen för Java-TDD

Tittar på att gå ett steg längre med TDD-workshops och lämna de grundläggande ämnena. Följande har efterfrågats:

  • testning med/av legacy code
  • vad är bra respektive dåliga test
  • funktionell eller acceptansdriven testning (ATDD)
  • beteende driven utveckling (BDD)

Egna saker jag själv skulle vilja gräva lite mer i och ägna ett par timmar åt:

  • hamcrest (matchers)
  • dotmesh (methods)
  • making EasyMock suck less
  • making Mockito suck
  • easyB
  • Fitnesse

I allmänhet så saknar jag en diskussion om hur lättredigerade test (wiki?) versionshanteras ihop med koden de testar eller är skrivna mot. Detta är ju högst intressant när man går in och gör en hot-fix för en produkt som rört sig mycket under ett år, och en kund som har produkten i drift sedan ett drygt år tillbaka vill sin fix. Hur kör man samma testsvit som man hade för ett år sedan på ett enkelt sätt? Hur är egentligen inte svårt. Jag har bara inte sett många bra lösningar, ännu. TextTest, xUseCase och liknande plain text-ramverk är en bra lösning. Frågan är bara om testen är tillräckligt tillgängliga för ATDD – hur får man kunden att känna att det är hans/hennes test?

Agile Testing Days 2010 coming up

Speaker at Agile Testing Days 2010

I'll Be There


In about six weeks I’ll give a talk at Agile Testing Days together with Emily Bache. The talk’s title is set to “The Coding Dojo
as a forum for teaching TDD” and we are last to speak on Wednesday before the final key note of the day (and the “chill out” event). I’m looking forward to the conference which I’m sure will be full of insights and rewarding in many ways.

Bok: Test-Driven Development

Test-Driven Development By Example

av Kent Beck

ISBN: 9780321146533

Detta är en bok som i tre steg visar hur Kent Beck tycker man skall skriva kod. Boken är lättläst, enkel att förstå och Beck är ganska tydlig i vad  han menar och hur han föreslår att man skall jobba.

Min behållning av boken är den lilla privata lappen med “test att skriva” – något som han alltså förespråkar men som jag själv aldrig använt i större utsträckning. Jag petar istället ner alla test-idéer i kod, typ:

// FIXME: testa null

Om jag skall ge mig på att sammanfatta vad han förespråkar så är det:

  • börja litet
  • använd en lista där du skriver upp testfall som du vet eller kommer på behöver testas
  • låt design växa fram
  • använd refaktoreringssteget till att skriva den riktiga implementation
  • misslyckas man med ett stort test, skriv ett mindre istället
  • få hellre ett test till att gå igenom än att ha vacker kod

Jag rekomenderar boken till någon som har ett hum om vad TDD är men som inte sett hur det kan fungera i praktiken. Kodexemplen är visserligen ganska lätta men det intressanta är att se hur han jobbar med problemlösning, vad TDD-metodiken ger och att det banne mig inte är svårt att börja.

assertThat(Hamcrest).looksNice();

I väntan på David Saff’s alternative assertThat(x).y() så nöjer jag mig med:

public class EmptyMatcher extends TypeSafeMatcher&lt;Collection < ?>> {
 
    @Override
    public boolean matchesSafely(Collection< ?> c) {
        return c.isEmpty();
    }
 
    public void describeTo(Description desc) {
        desc.appendText("empty");
    }
 
    @Factory
    public static lt;T> Matcher< ? super Collection<?>> isEmpty() {
        return new EmptyMatcher();
    }
}

som gör att man kan skriva trevlig enkelt läsbar kod, t ex:

@Test
public void filteringAnEmptyListReturnsAnEmptyList() {
    List anEmptyList = new ArrayList();
    List result = testee.filter(emptyList());
    assertThat(result, isEmpty());
    // men helst: assertThat(result).isEmpty();
}

Eclipse och TDD

Eclipse är ganska svagt utrustat från start för att köra TDD effektivt. Det verkar inte komma ifrån att code completion måste utföras med CTRL+mellanslag – här kommer IntelliJ för alltid lysa med sin vackerhet (där mellanslag eller tab är “markören” som kollar om den skall auto-complete:a).

Favorites

Följande klasser är bra att peta in i varje workspace Window » Preferences » Java » Editor » Content Assistant » Favorites:

  • org.junit.Assert.*
  • org.mockito.BDDMockito.*
  • org.mockito.Matchers.*
  • org.mockito.Mockito.*
  • org.mockito.MockitoAnnotations.*

Templates

Börja med att ta bort  alla SWT, ta bort test för JUnit 3.

WORK IN PROGRESS!

before

${staticImport:importStatic('org.mockito.MockitoAnnotations.initMocks')}
@${beforeAnnotation:newType(org.junit.Before)}
public void ${setup}() throws Exception {
  initMocks(this);
  testee = new ${cursor};
}

mock

@Mock private ${type} ${mock};

bdd – BDD Test

@Test public void statement() throws Exception {
    given(${mock}.${method}).willReturn(${value});
 
    // WHEN ${when}
    ${testee}.${act};
 
    // THEN ${then}
    verify(${mock}).${method}(${arguments});
}

tdd – TDD test

@Test public void statement() throws Exception {
    // Arrange
    // Act
    // Assert
}