why test driven development is “harder”

While I still don’t always do test driven development when coding at work, I do a lot of it.

I don’t always do TDD

  1. If I know the exact shape of the code before I start, it’s easier to create that shape before writing tests.  This happens a lot in web app development or when using generated code or certain framework.  I still write the tests with the code though. I think this happens because the interface I’m constrained by isn’t where I start thinking about the problem. When working on libraries or within a method/framework I do still TDD.
  2. For spikes.  If I have no idea how to approach something and just need to experiment.  I don’t know what tests to write because I don’t know what to do.

Ok, let’s suppose you’re working on an algorithm

This is something I find to be a great starting point for TDD.  It’s fairly obvious what the interface should be and most of the thought is on the implementation.  It is also a great example because you’ll want to try the same test cases repeatedly as you work making TDD save time.

Great, what makes TDD harder?

It’s not really.  The problem is when developers aren’t fluent in JUnit.  If the person coding isn’t good at writing tests, that becomes another thing to think about.  And when the mental load is higher, the task is harder.  The solution to this is to practice writing tests and get better at it.  Instead, some people merely complain that testing is hard and “expensive.”  Which becomes a sell fulfilling prophecy.

An example of how this affects me

I can think of three testing libraries that I’m at different levels of comfort with. And my reaction to writing a test in them. (just a regular test, forget about TDD here)

Library Comfort level Reaction
JUnit Fluent TDD, no problem.
HtmlUnit I have enough experience to know how to do common things and where I’m likely to hit a problem requiring more time. (I’m using it to test an app I didn’t write which makes things harder). While I’m comfortable writing tests, I’m limited for TDD.  I can definitely use TDD when fixing a bug.  But I couldn’t write a new screen that way.  I need the app to work enough to make sure my HtmlUnit test is right.
Selenium I know enough to know it changed a lot since I last used it. While my comfort level is a lot lower than HtmlUnit, I have the same feeling about TDD.  I could use it to fix a minor bug presuming there is enough app for me to test my Selenium code.  (And yes, Selenium as an HtmlUnit driver now which probably accounts for the similarity in reaction)

While I do have different feelings about TDD based on comfort level, one of the biggest differences is time.  It would take me a lot longer to write a Selenium test than a JUnit test.  That’s a sign that I need to practice/learn more/gain more experience.  Which is a perfectly normal part of coding.  We do need to plan for this.  Telling your developers to test with a tool they aren’t fluent in and not recognize it takes longer is a perfect way to invite no tests, poor tests or the quality of the code slipping.

Why was I thinking about this?

I’m working with someone on what I thought was an outline.  He suggested “I think a good way for us to communicate about these topics might be to first imagine …  questions we’ll want to ask”.  Kind of like TDD for an outline.  Think of what the student needs to know and get the “curriculum” from that.  I’ve never done that before and it was a lot harder than just writing an outline.  And I think the reasons it is “harder” are the same as for people new to TDD:

  1. A new way of thinking – I’ve never written questions before the objectives before.  People new to TDD aren’t used to thinking about how to test before they write the “real” code.
  2. Lack of experience with the “tool” – While I’ve written a fair number of questions, I’m by no means at the point that I feel fluent in doing so.  I’m probably just under where I feel with HtmlUnit in terms of experience there.  I know where many obstacles are but am still surprised often.
  3. More balls in the air – Just like thinking about both the tests and code in TDD, I had to think about both the questions and topics.

What is the takeaway

“Harder” doesn’t always mean harder.  Sometimes it means you need more skills and practice.  So if TDD seems “harder” to you, don’t run screaming.  You’ll get there.

certified scrum master

Passed the CSM (Certified Scrum Master) exam today with 34/35 correct which is 97.1%,

The Certified Scrum Master certification requires:

  • taking a two day class _ I like that the instructor made it electronic device free and threatened not to give credit to anyone mentally absent.
  • taking an online, unproctored test

About the test

The test is described well here.  The gist is that it is untimed, open book, unproctored and you don’t have to take it in one sitting.  The idea is clearly to reinforce what you learned in the class and ensure you were paying attention.  You need to get 24/35 correct which is about 68%.  You get 2 attempts and are given the correct answers once you pass.  If you need more attempts, they are $25 each.  Per the Scrum Alliance, the test is a mix of multiple choice and true/false.  (Or so the docs say – I didn’t get any true/false ones). It covers General Scrum knowledge, Scrum roles, Scrum meetings, and Scrum artifacts.

Once you pass, you are considered certified for 2 years at which point they ask you to pay $100 for another two years.  (by tying certification and membership together)

Some quotes indicated the test is really easy and more of a formality.  I agree that it is easy if you paid attention in class.  It is a good way to reinforce what you learned though.  “Certification” is probably too strong a word here.

My background

I’ve been doing parts of Scrum for about 2 years.  (The product owner isn’t as involved as he should be to actually call it Scrum.)  The point is that the material isn’t new to me.

Registering for the test on an iPad and popups

After the course, you get a link to the Scrum Alliance. At this point, you can take the test. It is offered in a number of different languages and run by mytestcom.net. I started the test on my iPad and quickly learned it requires you to allow pop ups. Went into ipad settings > safari and turned off block pop ups. It wasn’t immedidately obvious how to retry the pop up. But going back to the testcom homepage gave a clear link saying I was in the middle of a test. Then the iPad prompted me for whether to allow the pop up. I said yes, and was in.

Resuming the test on a ChromeBook and popups

WARNING: Don’t switch computers for the test.  Your bookmarks (questions to go back to) are stored in a cookie and not available on the second device.

I did half the test on my iPad and finished it up on a ChromeBook computer.  When I logged into Scrum Alliance with the ChromeBook, the button says “take CSM test in English”.  Which is fine.  But then the JavaScript says “are you sure you want to start the CSM test.”  Which I didn’t.  I wanted to resume.  Turns out that link is misleading and it does take you to resume your test.   And guess what?  The ChromeBook is set to not allow pop-ups either.  Ok.  Clicked the little window in the location bar to allow for this site and tried again.  Sadly, I spent about 10 minutes resuming the test.

Difficulty and time
I like to note how long each pass took and how it went. That gives a good sense of what to expect. Note that I think and test take a lot faster than average.

  • Pass 1 – 12 minutes – there were 17 questions that were so obvious, that I was comfortable answering them without more than 15 seconds of thought. And since the working of each was concise (no long scenario type things to read), this phase went rather quickly. The remaining 18 I was pretty sure of. I bookmarked them because i want to spend a little longer thinking about them or want to confirm in the Scrum book. Largely for learning purposes as I know that I already have enough right to get a passing score. Since I did phase 1 on my iPad, I also wanted to wait to be at a real computer to review and submit. Easier to look at the Scrum manual and test together on a real computer. Plus, i only had 10 minutes until my flight boarded
  • Pass 2 –  15 minutes – I had to go thru them all again because the bookmarks of which questions to go back to aren’t available on the ChromeBook.  I only looked up a few.  And even that was mostly to read more about the topic.  During this pass, I changed 1 answer.   There were 4 questions that I wasn’t 100% sure of.  I was able to narrow down to 2 choices and picked the one I thought best.  (Which worked out nicely)

Tips

  • Read carefully
  • Process of elimination is helpful
  • Don’t overthink it – they aren’t trying to trick you

Free Resources I used 

I actually looked at these between day 1 and day 2 to get a feel for what was going on.  After day 2, I didn’t do anything.  Then the morning following day 2, I did pass 1 of the test.

Resource My comments
Learning objectives and outline Good overview of what the course covers. Many parts will only make sense if you know the material though.
10 sample questions Easy if you know the material, but a good review.  I got one wrong, because I had never heard of the Product Backlog being referred to as the “Scrum Backlog”.
Scrum alliance open assessment This is more challenging than the official test and I learned more from it.

30 minutes, 30 questions, pass 85%.  Meant to evaluate your knowledge.  You can take it multiple times and get a few different questions each time. It requires 3rd party cookies which is annoying.  I took this three times after day 1 of the class and got 67%, 83% and 93% in that order.  The first two times, I did it from memory.  The third time, I used the actual Scrum guide as a reference.  (I’m not so good at remembering how long meeting X should be.  I know how long it is on our team, not the maximum.) It tells you what the correct answer is for the ones you got wrong.  Plus many have a paragraph explaining the rationale.  Making the by far the most valuable practice and reinforcement.  Both for the class and to learn more about Scrum.  This is definitely harder than the real exam as there can be multiple correct answers.

Resources I did not try

I don’t think you need them since the real test is open book and you can do research.

Resource My comments
Scrum Study Guide  This book is $50 for 50 pages.  It allegedly prepares you for the exam.  But the course does that.  I can’t imagine a book that short being worth the cost of $50 given this.  (I didn’t ask for a review copy because I suspect my review would be negative and I don’t want to approach a self-published author knowing that.)
Scrum Practice Test This is $7.  I looked at the preview on Amazon.  It seems harder than the exam, but interesting questions.
ScrumMaster Exam Questions E-book $20 book.  It’s 44 pages and you can preview the first four (along with the answers for free).  While some questions seem off topic (XP), the answer explanations are good.

 

smlunit – using without a python dependency

I’m currently taking the Coursera Programming Languages course which starts with ML.  Or more specifically SML/NJ.

Why I was looking at unit testing in SML

The instructor gave a test file with statements like:

val foo = function_to_write(1) = 2;

This is good in that it clearly shows the API and some of the expectations.  It’s not so good because you have to go thru the output to look whether all the values are set to true.  We were provided with 11 tests and told to write more.  I had 57 by the time I was done.  And I haven’t looked at the two challenge problems yet.  The instructor was very direct in saying we shouldn’t compare SML to languages we know because it impedes learning.  Well, I didn’t.  I compared the infrastructure.  And I learned more SML learning how this works than covered in week 1 of the class so I think I honored the spirit of this.

Choosing a SMLUnit implementation

I found two options in search

  1. SML Sharp‘s SML Unit – I found more references to this one on the internet.  However it requires steps to install and looks like it takes longer to get started with.
  2. SML Unit – This is the #1 hit on google for SML Unit and appears to be something written by a university student.  It’s very good though and I recommend it.

Python dependency

SMLUnit comes with good documentation and examples.  It also comes with a runner that uses Python to kick off the tests and report on the status.  This can’t be done purely in SML because reporting on the results requires state.

I’m sure it is a good runner, but I didn’t notice it existed.  (I started on the code page with the assertions not the main page that explains all this.)  Since I went to the (minor) trouble to create a runner in UNIX,  I’m posting it in case anyone wants to test SML on a machine that doesn’t have Python.  Not likely I know – most machines have Python.

The runner

The runner feeds your unit tests to SML and then reports on whether there were any failures.


# Since sml is a functional language, I couldn't figure out a way to output a summary
# at the end as to whether any tests failed. Wrapping in a shell script to avoid
# this problem. [realized afterwards it comes with a Python runner]
#
# Usage:
# smlunit_runner.sh name_of_tests.sml
#
# Assumes the sml test suite has "use" statements for all dependencies including smlunit

if [ $# -eq 0 ]
then
 echo "SML test file is mandatory"
 exit
fi

OUTPUT=`cat $1 | /usr/local/smlnj/bin/sml`

echo "$OUTPUT"

NUM_FAIL=`echo "$OUTPUT" | grep "^FAIL$" | wc -l`
NUM_PASS=`echo "$OUTPUT" | grep "^OK$" | wc -l`

echo ""
echo ""
echo "Test summary: (also look at last output to make sure not a stack trace)"
echo "$NUM_FAIL tests failed"
echo "$NUM_PASS tests passed"

What do the tests look like?

Code – helloWorld.sml

fun hello_world() = "hello"

fun add(a:int, b:int) = a + b

Tests – helloWorldTest.sml

use "asserts.sml";

<em id="__mceDel">use "helloWorld.sml";</em>

assertTrue true "assert true";
assertEqual "hello" (hello_world()) "compare two values";
assertEqual 3 (add(1,2)) "compare two values again";

And what about the asserts?

asserts.sml is a direct copy of smlunit.sml


(* from https://github.com/dellsystem/smlunit/blob/master/lib/smlunit.sml *)

fun roundish (x:real) = Real.realRound(x * 100000000000.0) / 100000000000.0;

fun assert expr1 expr2 (desc:string) function =
 (print ("*********** " ^ desc ^ " ***********\n" );
 (if function (expr1, expr2) then
 print "OK\n"
 else
 print "FAIL\n"
 );
 [expr1, expr2]);

fun assertEqual expr1 expr2 (desc:string) = assert expr1 expr2 desc (fn (x, y) => x = y);
fun assertRealEqual (expr1:real) (expr2:real) (desc:string) = assert expr1 expr2 desc (fn (x, y) => Real.== (roundish(x), roundish(y)));

fun assertTrue expr desc = (assertEqual expr true desc);
fun assertFalse expr desc = (assertEqual expr false desc);

(* Functions for comparing a lot of things in one list *)
fun assertReals f [] (desc:string) = []
 | assertReals f ((input, output, expl)::t) (desc:string) =
 (assertRealEqual (f input) output (desc ^ ": " ^ expl)) @ (assertReals f t (desc));

fun assertRegulars f [] (desc:string) = []
 | assertRegulars f ((input, output, expl)::t) (desc:string) =
 (assertEqual (f input) output (desc ^ ": " ^ expl)) @ (assertRegulars f t (desc));

Comments?

I have less than 5 hours experience with SML   (I did know LISP in college and recursion certainly isn’t new.)  So I’m sure there are naming conventions and the like that I’m not following.  I look forward to hearing comments on what I did.