Tuesday, January 31, 2012

Exercise 51: Getting Input From A Browser: Learn Ruby the Hard Way: Practicum

All right, so we have a simple Sinatra framework up and running. Now let's see if we can do something just a little more exciting, shall we :)?


This time around, we'll make some interactive elements. We will submit text to our application by using that well known method, the form. Additionally, we'll look at ways that we can do automated testing for forms.




How The Web Works (The Boring Bits)




Zed's got this pretty well nailed down, so I'll let him tell this part :):

- You type in the url http://learnpythonthehardway.org/ into your browser and it sends the request out on line (A) to your computer's network interface.


- Your request goes out over the internet on line (B) and then to the remote computer on line (C) where my server accepts the request.


- Once my computer accepts it, my web application gets it on line (D), and my web application code runs the / (index) handler.


- The response comes out of my web server when I return it, and goes back to your browser over line (D) again.


- The server running this site takes the response off line (D) then sends it back over the internet on line (C).


- The response from the server then comes off the internet on line (B), and your computer's network interface hands it to your browser on line (A).


- Finally, your browser then displays the response.

Rather than go through a full breakdown of what the web terms mean, I'll let the reader take a look at Zed's very well done crash course explanation over at http://ruby.learncodethehardway.org/book/ex51.html (chances are, if you've gotten this far with me, you already know the links and site very well.

How Forms Work

Let's take the lib/gothonweb.rb file make some changes to it:


- Restart Sinatra (hit CTRL-C and then run it again) to make sure it loads again



- With your browser go to http://localhost:4567/hello which should display, "I just wanted to say Hello, Nobody."



- Next, change the URL in your browser to http://localhost:4567/hello?name=Frank and you'll see it say "Hello, Frank."



Finally, change the name=Frank part to be your name. Now it's saying hello to you.



So what have we done here?


- We're now using the "params" hash with a value of ":name" to get data from the browser. Sinatra takes all of the key/value pairs after the ? part of the URL and adds them to the params hash for you to work with.

- The greeting is then constructed from the value of ":name". By default we set this to "Nobody". If we give it a name value on the command line, it changes it based on the "name=EnteredName" that we put in the URL after the "?"

We can add more than one param on the command line, too if we modify the script to accept the changes.


We can change the code to get params[:name] and params[:greet] as well like this:



By default, it looks like this:



And with the url values, it looks like this:

Example:
http://localhost:4567/hello?greet=Wassup&name=Michael




Creating HTML Forms


OK, so we can pass the values through the URL, but let's face it, that's a pain. Most people expect to enter information in the browser directly and hit a button. this uses the time honored web feature called a form (or a POST form, to be more specific). A form is just an HTML file with a "form" tag in it. This form will collect information from the user, then send it to your web application just like you did above.

Let's make a quick form to see how this works (this is being done in  lib/views/hello_form.erb):


Now make some changes to gothonweb to be able to accept the form:


Once you've got those written up, simply restart the web application again and hit it with your browser like before.




The part of the hello_form.erb file that makes this work is the line with
. This tells your browser to:

- Collect data from the user using the form fields inside the form.

- Send them to the server using a POST type of request, which is just another browser request that "hides" the form fields.

- Send that to the /hello URL (as shown in the action="/hello" part).


Creating A Layout Template

For the final exercise, we'll be making a bunch of small HTML pages. Having to always code up a page each time will soon become tedious, so we'll create a simple "layout" template to wrap all of our pages with common headers and footers.

So here's the change to lib/views/index.erb:



Change lib/views/hello_form.erb to be like this:



This removes all of the general "boilerplate stuff" that every page will have at the top and the bottom, and now we'll make a layout page that contains all of that:

Here's lib/views/layout.erb file that handles it for us from now on.

Once you have those changes, create a lib/views/layout.erb file with this in it:




Writing Automated Tests For Forms

So now that we have made these changes, we could keep loading up the web page each time to see if we have made the correct changes... or we could use our unit tests to see if what we have put in works, too. The tester in me would like to see us do both, so lets do that :).

Create the file test/test_gothonweb.rb with these contents:



Finally, run test/test_gothonweb.rb to test your web application:

$ ruby test/test_gothonweb.rb
Loaded suite test/test_gothonweb
Started
.
Finished in 0.023839 seconds.


1 tests, 9 assertions, 0 failures, 0 errors, 0 skips


Test run options: --seed 57414

Note: what's being seen here is not what I am seeing. Maybe there is a step missing, but the framework appears to be running as expected. Again, it's a problem I'l tweak a bit more later.

Zed explains that what is happening here is that we're importing the whole application from the lib/gothonweb.rb library, then running it manually.

The rack/test library we have included has a very simple API for processing requests. Its get, put, post, delete, and head methods simulate the respective type of request on the application.

- All mock request methods have the same argument signature:

get '/path', params={}, rack_env={}

- /path is the request path and may optionally include a query string.

- params is a Hash of query/post parameters, a String request body, or nil.

- rack_env is a Hash of Rack environment values. This can be used to set request headers and other request related information, such as session data.

This works without running an actual web server so you can do tests with automated tests and also use your browser to test a running server.

To validate responses from this function, use the assert_response function from test/test_gothonweb.rb which has:

assert_response(resp, contains=nil, matches=nil, headers=nil, status=200)


TESTHEAD's TAKEAWAYS:

This is pretty cool, again, this helps make a lot more sense out of what I've been seeing in the code and the rails applications that I use (the boilerplate loading up the header and the footer that's the same, and then the specific code elements being loaded as needed and only when needed, it's a beautiful thing. The Unit tests are not behaving the way that I expect them, to, but again, it's possible I'm missing something or I configured something wrong. Even without this specific aspect, I think the point has been made. Sinatra makes for an elegant little framework for running a server.

Monday, January 30, 2012

Exercise 50: Your First Website: Learn Ruby the Hard Way: Practicum

Cool, we have finally reached the point where we interact with the web and web components using Ruby.


The example text uses the Sinatra framework.


Having heard of Sinatra in various places, I've been interested in seeing how to interact with it (and see how it differs from Rails, which is an environment I already use and test in my "day job" :).


Installing Sinatra


Using gem install Sinatra:



Make A Simple "Hello World" Project


Now you're going to make an initial very simple "Hello World" web application and project directory using Sinatra. First, make your project directory, and then create the structure by running "bundle gem gothanweb (gothan being the game we've been working with for the past while):

Now let's make a very basic Sinatra application by putting the following code into lib/gothonweb.rb:
Then run the application like this:


Finally, use your web browser and go to the URL http://localhost:4567/.

Well, this is what I see:



What's Going On?

Here's what's happening when your browser hits your application:

- The browser makes a network connection to your own computer on port 4567.

- Once it connects, it makes an HTTP request to the lib/gothonweb.rb application and asks for the / URL, which is commonly the first URL on any website.

- Inside lib/gothonweb.rb there are blocks of code that map to URLs. The only one we have is the '/' mapping.

- Sinatra calls the matching block, which simply returns a string for what Sinatra should send to the browser.

- Finally, Sinatra has handled the request and sends this response to the browser which is what you are seeing.


Fixing Errors

Comment out line 6 where you assign the greeting variable, then hit refresh in your browser. 



You should see an error page now that gives you lots of information on how your application just exploded. You know that the variable greeting is now missing, but Sinatra gives you this nice error page to track down exactly where. Do each of the following with this page:

- Look at the sinatra.error variable.

- Look at the REQUEST_ variables and see if they match anything you're already familiar with. 

- Uncomment line 6 and all returns back to normal.





Create Basic Templates





The following steps will make a properly formed "web page". This page used the embedded ruby extension [filename.erb]. It's stored in lib/views.

The first step is to create a lib/views/index.erb file that looks like this:
Now we modifying the lib/gothonweb.rb script, so that Sinatra has a way to access the ERB file:


So what happens if we reload the web page with these changes?

And just to show that it's properly formsed HTML...:
So what's going on here?

- In lib/gothonweb.rb we added an erb method call.

- The erb method loads .erb files out of the lib/views/ directory. We pass it index.erb because we're passing that as a parameter (erb :index ...).

- Now, when the browser hits / and lib/gothonweb.rb matches and executes the get '/' do block, instead of just returning the string greeting, it calls erb and pass greeting to it as a variable.

- Finally, the HTML in lib/views/index.erb contains Ruby code that tests the greeting variable, and prints a message using the greeting.


TESTHEAD's TAKEAWAYS:

So this is a very simple and basic example, but it shows that we can fairly quickly develop a web site within a framework and use Ruby to pass variables for the values it would expect to see. That's pretty cool :).





Exercise 49: Making Sentences: Learn Ruby the Hard Way: Practicum

For the record, here's the point where people get moderately bent at programming books when they can't seem to figure something out. Again, this is my problem, not Zed or Rob's, but it does point out what often comes to be a challenge for many.


When you get stuck on a concept, oftentimes, there really isn't a way to move forward until you figure it out. While I don't want to get all the way through the book and decide I'm stranded on one point, two exercises call for me to have my act together on this functionality (which makes perfect sense, because in life, you have to make the system work before you can add new features.


Thus, I'm reviewing this chapter with a significant handicap; I'm still stuck from Exercise 48.

So if we have managed to get the lexicon scanner to work, we should see output that looks something like this:



ruby-1.9.2-p180 :003 > print Lexicon.scan("go north")
[#<struct Lexicon::Pair token=:verb, word="go">,
    #<struct Lexicon::Pair token=:direction, word="north">] => nil
ruby-1.9.2-p180 :004 > print Lexicon.scan("kill the princess")
[#<struct Lexicon::Pair token=:verb, word="kill">,
    #<struct Lexicon::Pair token=:stop, word="the">,
    #<struct Lexicon::Pair token=:noun, word="princess">] => nil
ruby-1.9.2-p180 :005 > print Lexicon.scan("eat the bear")
[#<struct Lexicon::Pair token=:verb, word="eat">,
    #<struct Lexicon::Pair token=:stop, word="the">,
    #<struct Lexicon::Pair token=:noun, word="bear">] => nil
ruby-1.9.2-p180 :006 > print Lexicon.scan("open the door and smack the bear in the nose")
[#<struct Lexicon::Pair token=:error, word="open">,
    #<struct Lexicon::Pair token=:stop, word="the">,
    #<struct Lexicon::Pair token=:noun, word="door">,
    #<struct Lexicon::Pair token=:error, word="and">,
    #<struct Lexicon::Pair token=:error, word="smack">,
    #<struct Lexicon::Pair token=:stop, word="the">,
    #<struct Lexicon::Pair token=:noun, word="bear">,
    #<struct Lexicon::Pair token=:stop, word="in">,
    #<struct Lexicon::Pair token=:stop, word="the">,
    #<struct Lexicon::Pair token=:error, word="nose">] => nil
ruby-1.9.2-p180 :007 >


With this output, we should be able to now take the token pairs and make an actual sentence, using a Sentence class.

Sentences can be structured simply by combining the following tokens (for English, anyway; different languages will have different rules):

Subject Verb Object

So the primary goal of the sentence class is to turn the lists of structs above into a Sentence object with a subject, verb, and object.

Match And Peek

To do this we need four tools:

- A way to loop through the list of structs.

- A way to "match" different types of structs that we expect in our Subject Verb Object setup.
- A way to "peek" at a potential struct so we can make some decisions.
- A way to "skip" things we do not care about, like stop words.
- We use the peek function to say look at the next element in our struct array, and then match to take one off and work with it.

So here is the first peek function:

def peek(word_list)
  begin
    word_list.first.token
  rescue
    nil
  end
end

This is the match function:

def match(word_list, expecting)
  begin
    word = word_list.shift


    if word.token == expecting
      word
    else
      nil
    end
  rescue
     nil
  end
end

This is the skip function:

def skip(word_list, word_type)
  while peek(word_list) == word_type
    match(word_list, word_type)
  end
end


The Sentence Grammar

To build our Sentence objects from the struct array, we can do the following:

- Identify the next word with peek.

- If that word fits the grammar, call a function to handle that part of the grammar

- If it doesn't, raise an error (see below).

When we're all done, we should have a Sentence object to work with in our game.

So this time, instead of being given the test and trying to figure out the code, this time, we get the code and we then figure out how to write the test to meet the requirements.

Here's the code for parsing simple sentences using the ex48 Lexicon class:



The sections below are advice given by Zed and Rob. It's printed in italic to show it's their words verbatim.

A Word On Modules

This code uses something in Ruby called a "module" named Parser. A module (created with module Parser) is a way to package up the functions so that they don't conflict with other parts of Ruby. In Ruby 1.9 there was a change to the testing system that created a skip method which conflicted with the Parser.skip method. The solution was to do what you see here and wrap all the functions in this module.


You use a module by simply calling functions on it with the . operator, similar to an object you've made. In this case if you wanted to call the parse_verb() function you'd write Parser.parse_verb(). You'll see a demonstration of this when I give you a sample unit test.


What You Should Test

For Exercise 49 is write a complete test that confirms everything in this code is working. That includes making exceptions happen by giving it bad sentences. Here is a starter sample so you can see how you would call a function in a module:

require 'test/unit'
require_relative '../lib/ex49'


class ParserTests &lt; Test::Unit::TestCase


    def test_parse_verb()
        # WARNING: THIS FAILS ON PURPOSE SEE THE BOOK
        Parser.parse_verb([false])
    end


end

You can see I make the basic test class, then create a test_parse_verb to test out the Parser.parse_verb function. I don't want to do the work for you, so I've made this fail on purpose. This shows you how to use the Parser module and call functions on it, and you should work on making this test actually test all the code.


Check for an exception by using the function assert_raise from the Test::Unit documentation. Learn how to use this so you can write a test that is expected to fail, which is very important in testing. Learn about this function (and others) by reading the Test::Unit documentation.


When you are done, you should know how this bit of code works, and how to write a test for other people's code even if they do not want you to. Trust me, it's a very handy skill to have.

Extra Credit

-  Change the parse_ methods and try to put them into a class rather than be just methods. Which design do you like better?
- Make the parser more error resistant so that you can avoid annoying your users if they type words your lexicon doesn't understand.
- Improve the grammar by handling more things like numbers.
- Think about how you might use this Sentence class in your game to do more fun things with a user's input.

Book Review: The Cucumber Book

One of the cool things about Pragmatic Publishing is the fact that they make it possible to get your hands on Beta books, meaning you get the chance to see a book as its actively being developed. The Cucumber Book was one of those books, and as such, I’ve had the benefit of looking at and reviewing this book for the past several months, and have watched it grow into the book that is today (and now available in print form).


Most people who have a passing understanding of Test Driven Development or Behavior Driven Development have likely heard of Cucumber. It’s a language that allows anyone who wants to define tests and requirements for applications the ability to do so in plain English (or fill in the blank language if supported). In truth, Cucumber isn’t really a programming language at all, but a symbolic phrase library that matches to various underlying commands and blocks of code (represented in Ruby in this book and referencing a variety of tools including Capybara, Rspec and others).


Matt Wynne and Aslak Hellesøy have put together a very readable and focused text that help the user get familiar with the basics of the language. The book also focuses the reader on understanding the underpinnings needed to create expressions that work with their respective technologies. Granted, if you are a tester and you want to take advantage of this framework, there is plenty in here to keep you busy. The Cucumber Book starts out by explaining what Cucumber is and the niche it is meant to fill (specifications based tests and requirements). If you are a developer, there is likewise plenty in here to keep you interested, too.


The process in the Cucumber book is heavy on examples and showing how the examples work. Yes, for those who want to know how to use the syntax and language specific details of Cucumber, that stuff is covered. What is also covered, and covered well, is the Behavioral Driven Development approach needed to effectively create tests and have them work effectively. Along with creating feature files and steps for those feature files, the underlying step definitions also have to be coded. Not only do they have to be coded, but they have to have assertions written that will effectively confirm if the step has passed, or if it fails, and why.


Since the book is primarily based on Cucumber, there is a large section that covers Cucumber fundamentals, including basic Gherkin (the underlying syntax that Cucumber uses), and the ability of using expressive options such as Scenario Outlines, Data tables, Doc Strings, tags, and dealing with some of the pain points seen in your tests (such as "flickering scenarios", where the tests pass some of the time but fail some times, too). More than just using Cucumber to define steps and have step definitions defined, the third part of the book deals with applying Cucumber to a number of different technologies; working with various databases, testing with RESTful web services, working with Rails, running tests and using capybara to simulate common browser actions and many other options that may come to play in your everyday testing life.


Bottom Line:


If you have ever been interested in looking at Cucumber and your testing environment is built around Ruby, then this will be an ideal book to use. If you are interested in deploying Cucumber in another type of environment, such as testing with Java or .NET, many of the ideas in this book will also carry over, but have a look at “The Secret Ninja Cucumber Scrolls” by David de Florinier and Gojko Adzic. It provides information about how to apply Cucumber to those environments. Regardless of your particular focus and environment needs, for a practical and effective book for learning and using Cucumber in a meaningful way, The Cucumber Book is an excellent addition to any tester or developer’s library.

Exercise 48: Advanced User Input: Learn Ruby the Hard Way: Practicum

So it's been awhile since I've posted one of these practicum updates. I could say there's a lot of reasons why. I got sidetracked into doing a tester's autobiography, or that my work and family life accelerated into areas that I needed to get taken acare of and this had to take a back burner. I could say all of those things, but they'd be excuses. No, the reason why I haven't posted in awhile is that, well, I'm stuck.

this is the first assignment I have not been able to get to work, and I think it's because of what it requires us to do. zed has given us a test, and we are to write the code to make the tests pass. So far, I've not been able to do it. that probably says a whole lot more about me than it does Zed, but be that as it may, I cannot call this project complete or objective if I only post the things I can do well. I said I'd also post the areas I was struggling with, and well, here they are:

The point to this assignment is that, right now, if we want to use our game and answer questions in the game, we have to be exact in our terminology. "Open the Door" is OK, but:

- open door
- go THROUGH the door

will cause an error or not give us the right response, even though they are saying the same thing.

the goal is that we want to write some classes that will work as a library of possible responses, and in this regard, we want to do the following:


- We have Words separated by spaces.
- We have Sentences composed of the words.
- We have Grammar that structures the sentences into meaning.

Our Game Lexicon

In our game we have to create a Lexicon of words:

Direction words: north, south, east, west, down, up, left, right, back.
Verbs: go, stop, kill, eat.
Stop words: the, in, of, from, at, it
Nouns: door, bear, princess, cabinet.
Numbers: any string of 0 through 9 characters.


Breaking Up A Sentence

The process to break up a sentence into individual words is fairly simple, and looks like this:

stuff = gets.chomp()
words = stuff.split()

Below is what Zed and Rob provide to help us understand what is happening. On the surface, I get what they are saying, but getting my left hand to get what the right hand is doing, I'm still working through (note, if I figure this out, or someone helps me through this, I will post the solution provided and credit to the person who helps me figure it out :) ).

Lexicon Structs

Once we know how to break up a sentence into words, we just have to go through the list of words and figure out what "type" they are. To do that we're going to use a handy little Ruby structure called a "struct". A struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class. It's created like this:

Pair = Struct.new(:token, :word)
first_word = Pair.new("direction", "north")
second_word = Pair.new("verb", "go")
sentence = [first_word, second_word]

This creates a pair of (TOKEN, WORD) that lets you look at the word and do things with it.


Scanning Input

Now you are ready to write your scanner. This scanner will take a string of input from a user and return a sentence that's composed of a list of structs with the (TOKEN, WORD) pairings. If a word isn't part of the lexicon then it should still return the WORD, but set the TOKEN to an error token. These error tokens will tell the user they messed up.


Here's where it gets fun. I'm not going to tell you how to do this. Instead I'm going to write a unit test und you are going to write the scanner so that the unit test works.

Exceptions And Numbers

An area that Zed has provided for us to consider when it comes to converting numbers:


There is one tiny thing I will help you with first, and that's converting numbers. In order to do this though, we're going to cheat and use exceptions. An exception is an error that you get from some function you may have run. What happens is your function "raises" an exception when it encounters an error, then you have to handle that exception. For example, if you type this into IRB:

ruby-1.9.2-p180 :001 > Integer("hell")
ArgumentError: invalid value for Integer(): "hell"
    from (irb):1:in `Integer'
    from (irb):1
    from /home/rob/.rvm/rubies/ruby-1.9.2-p180/bin/irb:16:in `
'


That ArgumentError is an exception that the Integer() function threw because what you handed Integer() is not a number. The Integer() function could have returned a value to tell you it had an error, but since it only returns numbers, it'd have a hard time doing that. It can't return -1 since that's a number. Instead of trying to figure out what to return when there's an error, the Integer() function raises the TypeError exception and you deal with it.


You deal with an exception by using the begin and rescue keywords:

def convert_number(s)
  begin
    Integer(s)
  rescue ArgumentError
    nil
  end
end

You put the code you want to "begin" inside the begin block, and then you put the code to run for the error inside the rescue. In this case, we want to call Integer() on something that might be a number. If that has an error, then we "rescue" it and return nil instead.


In your scanner that you write, you should use this function to test if something is a number. You should also do it as the last thing you check for before declaring that word an error word.

What You Should Test

Here are the files test/test_lexicon.rb that I am working with:



Design Hints

Focus on getting one test working at a time. Keep this simple and just put all the words in your lexicon in lists that are in your lexicon.rb file. Do not modify the input list of words, but instead make your own new list with your lexicon pairs in it. Also, use the include? method with these lexicon arrays to check if a word is in the lexicon.

Extra Credit

- Improve the unit test to make sure you cover more of the lexicon.
- Add to the lexicon and then update the unit test.
- Make your scanner handles user input in any capitalization and case.
- Update the test to make sure this actually works.
- Find another way to convert the number.
- My solution was 37 lines long. Is yours longer? Shorter?

TESTHEAD's TAKEAWAY:

Test Driven Development is not as easy as it seems, at least as I currently understand it. Again, I'm not blaming Zed or Rob here, I'm blaming myself for not quite geting how to do this. this and the next ercise are by necessity going to need to be considered "open ended" for the time being until I can grok what I need to do to make this work. Sometimes that takes beating against it, sometimes it means doing something else until I can see the connection. Either way, my goal was to review and complete this by the end of January, and I'm running low on time now, so I need to get a move on and come backto this one later.

Maybe There's a Better Way (Thank You, Two Leaf Clover :) )


As many of you know, Aaron Scott and I have been doing some cross pollination with each other's sites. When he posts something that I think might elicit a fun or insightful post on my end, I use one of his cartoons to help illustrate the point. It's been my hope also that I've helped some testers discover his strip, Two Leaf Clover and enjoy it as well.

Well, Aaron did something cool for me today. He made a cartoon just for me (well, for everyone really, but it's something we talked about a number of times). This strip will now reside on TESTHEAD permanently in the upper corner as a reminder to all of us, that we don't have to accept what has come before, and that the traditions of old need not define our future.

As some have seen in the past, the "mascot" of the TESTHEAD site is the crash test dummy. It's a metaphor for getting information without us getting hurt. Of course, I've used the crash test dummy as a metaphor for myself as a tester. How often do I just go in and do stuff that doesn't seem to make any sense? How often do I run through endless checklists of steps because "we've always done it that way?" I told Aaron that I wanted to see TESTHEAD and other testing blogs be a way to help "empower the dummies" so that they don't have to specifically just be launched at walls, that they could say "maybe there are better ways to do things that we haven't considered yet".

Oh, and I think it's pretty cute, too.

So again, my thanks to Aaron for effectively making a TESTHEAD specific cartoon, and one that I can show, well, for always on here. It's much appreciated. For those who are not familiar with Two Leaf Clover, go pay Aaron's site a visit :).

Sunday, January 29, 2012

Where I Am Today: A Meandering Walk Through Twenty Years of Software Testing

As I made my way into the small loft on the fourth floor of an old brick building on Jessie Street in the South of Market area of San Francisco, I had a new opportunity to start over again with a different kind of company. When SideReel hired me, they were focusing on developing a solid Agile team and releasing software regularly. Like many organizations, they were heavily involved with Test Driven Development and doing much of their testing within their group. It worked in some areas but they wanted to have a better idea from outside of their group as far as testing was concerned, and that's where I came in.


SideReel, for those who are not familiar, is a television aggregator. It allows users to find, watch and keep track of television shows, movies, and WebTV programs. We have also made pushes to share that information with other users and help make it a "social" experience, so that, if you want to, you can recommend shows to others and let them know what you are watching. It's a pure web and mobile play, which means that the site is 100% online, and all of the assets of the site and software are deployed online as well. No software needs to be downloaded and installed, but browser compatibility and appearance is a big deal, and something I spend a fair amount of time with.


At the time, SideReel had been around for about three years, and had started in the living room of one of the founders, and had grown over time. While they were larger and had a bigger business than Tracker did when I got there, that same "family vibe" was definitely there, and I liked that a lot. I knew that I had a chance to be involved in something very different than anything I'd worked with in the past, and that was what was most appealing about the opportunity.


I had worked in many different types of environments, but Agile was a new experience. While Tracker had tried examining and implementing some elements of it into our process, this was the first time I'd seen a team that actively practiced it in most of their development work. I found the first few weeks when I was there, when I started working on test plans the way I always had, to be enlightening. Rather than having to spend so much of my time working with writing test plans that were scripted out, I was encouraged instead to examine the stories in the tracking system we were using, and to append my tests there. What? No over arching test plan? No long term back and forth over the quantity and details of plans? How crazy was that? It turns out, not so crazy at all. While it seemed odd to have everything associated with just an individual story, it made sense since the stories in question were sliced so thin that the functionality was encapsulated in those areas, and therefore my tests were realistically touching just a few areas; I could focus them into just the parameters of an individual story. I liked this model because it actually fit better with the notion I had of what  tester actually did, which was to provide information about what a product does, and allow me to focus on the areas that actually mattered. With the use of Continuous Integration for each check in, we had much of the regression areas covered (not all, as I would find out, but a lot of them). 


SideReel places a lot of value on exploratory testing, and it felt good to actually be able to apply that in a real sense. It's not that other places didn't value it, but that it was an area that wasn't really understood or given much focus in the past. Having a team that had taken the Test Driven Development approach to heart and emphasizing writing tests before writing code certainly helped in that regard. They also provided a large library of tests that had been written so that I could see what they were looking for at the code level and expand on it to see if there were other questions I could ask and get involved with.


This wild world of start-up madness, I would discover, would be short lived. I was only with the company for six weeks when I found out that SideReel was to be acquired by Rovi Corporation, which was itself an owner of numerous companies related to video an audio content, information and other properties related to entertainment (their holdings included Sonic Solutions, Roxio, AllMusic, Divx and several other brands). We were told that, while we would be part of a larger organization's structure and business model, our day to day operations as SideReel would largely go unchanged. While we would relocate to a new building and have our own area of that building, we would still be operating as though we were the same 20 people that were in the walk up flat on Jessie Street.


As we started to make the changeover, I was challenged by the development team to actively learn and get involved with writing automated tests for SideReel. My goal was to work from the idea that I didn't have access to the fundamentals of the code, and to focus on the front facing user experience wherever possible. The goal was to put together a battery of smoke tests that would give us confidence that any new features rolled in would not cause undue problems or challenges to our users. With that, I began to spend a lot more time learning about Cucumber, the underlying tools that worked with it (Capybara and RSpec), and learning as much Ruby as I could. This was a first. While in the past my ability to use automation and computer assisted testing was left to me to do as much or as little as I wanted, the goal of SideReel was to have me be as knowledgeable as possible of the test driven development approach that they used.


During this year, there was also a big emphasis on my part to write a lot more. TESTHEAD was one of those mediums, but so was getting published in various online journals related to software testing. It seems each time I had a chance to write something for one journal, another would contact me and ask if I could write for them as well. 2011 also saw the "How to Reduce the Cost of Software Testing" book be released and, needless to say, I was excited to be a part of that title and to be able to share with my management team that I was a contributor to that project. My goal was to show them that they had a dedicated and involved tester who was excited about being actively engaged in the testing community. I also enjoyed the opportunities that I had when various testers would come to the Bay area and we'd be able to get together and talk about developments and opportunities. I got involved with taking and then teaching the Bug Advocacy class, which is the second of the Black Box Software Testing classes offered by AST. I participated as a volunteer for the first Selenium Conference which was held in San Francisco, and developed two talks this year, one for CAST 2011 in Seattle and one for PNSQC 2011 to be in Portland. I also made a point of reviewing as many books as I could during the course of the year, with a number of publishers giving me access to lots of great titles to explore and learn from.


In a way, I had to deal with a slightly different challenge than I had dealt with at Tracker. Whereas I was dealing with overcoming boredom at doing the same thing over and over, the challenge I was now facing was keeping a balance between all of the amazing opportunities I was getting the chance to get involved with. When I told my team that I had been elected to the Board of Directors of AST, they were congratulatory, but I also spent some time talking with one of our founders about some of his concerns. While he was excited for me and happy to have someone so engaged in testing, he also had some legitimate fears that I was so involved and engaged that it would have a negative effect on what I was doing for them. While my goal was not to be distracted from doing my job, I could see it was entirely possible that too much testing could get in the way of doing testing (I know that looks odd, but it's actually true. He meant that I'd be so focused on talks, articles and AST business that I'd pay less attention to the testing needs that SideReel has).  I assured him that my goal was to do great things in the world of Software Testing if I could, and that that started with doing great things for SideReel. That was my first priority, and that it would be going forward. That actually takes some doing at times, but it also allowed us to set up some plans as to what areas of testing and blogging are "on the clock" and which areas are best spent after hours to explore and consider.


I've mentioned many times on this site the calamity that befell me in August of 2011, with a severely broken leg and the resulting recovery time. That experience actually took me out of the running for being able to present my proposed talk at PNSQC in October (it was still hard to move around at that time; I'd literally spent the month of September in bed or with my leg elevated). It did give me a chance to read more and dive into some areas of testing I hadn't had a chance to explore previously, and I had a chance to sign on for the roll-out of the third class in the Black Box Software Testing series, which was Test Design. This would be an interesting place for me to be, in that I was actually helping to teach a class in its pilot run that I had not actually taken. I had to review the materials a few weeks before the start of the class and get an understanding of the material so that I could help teach it as well.  It was a fun experience, but occasionally it felt like I was getting lost in the weeds. This was a big class and it had a lot of information to absorb, but overall I think we did a good job.


I'd be remiss if I were to let 2011 go and not talk about one of the initiatives I most enjoyed being involved in, and that was Weekend Testing. We put on two dozen testing clinics during the course of the past year, and I had a chance to actually discuss the process and do it live at CAST 2011. The real credit, of course, goes to the many participants from all over the world (not just from the Americas) that participated and got involved with our sessions, asked great questions, and offered suggestions for follow-on sessions.


2012 is now just underway, and my involvement with testing is stronger than ever. I look forward to a year where I will be able to learn more, get involved where I can and discover more opportunities, and in some small way be actively engaged with both my own company and with the broader community of testers in the Bay Area and in the world. The cool thing about software testing is that the only limits there are are the ones you place on yourself. The broader community is more than happy to help fellow testers learn more, do more, get more involved and be more engaged.


So what has this last year taught me?


- There's a huge benefit to standing up every day and saying what you have done and what your plans are for that given day. There's a level of accountability that document controls, sign offs an many other methods don't have. When you verbalize your commitments, they feel much more real and tangible, and you feel much more beholden to making sure they get finished.


- Agile methodologies do help to make testing more focused and help make the process of testing likewise more focused. Rather than having to deal with the changes to a product and having to test everything every single time, the ability to take a thin slice of the product allows the tester the ability to get closer to a more complete level of testing (note, I said more complete; it's still impossible to get to a totally complete level of testing, even in the agile space, but you can get  lot close to that goal when you don't have to deal with the entire product).


- Being an embedded tester within and Agile team has its benefits. It's nice to just be able to get up and show something to a developer sitting right behind me or across from me rather than having to invade someone's cube. It's a much faster process and a lot more effective.


- Automation is like any other skill. It takes time and patience to learn it, practice with it, suck at it at first, and slowly over time get better at it. I realize now that my biggest problem in the past was that I didn't really give myself enough time to absorb what I needed to do, not did I give myself enough daily practice to be able to actually have enough to absorb. Just like a batter doesn't go in and immediately hit home runs off a top notch pitcher, so a tester will not be able to write flawless test code the first time out. Start small, make some things work correctly, then branch out. Also, if you need a developer to help you, don't be afraid to ask, but go in with very specific questions, such as "which class should I be using if I want to test the ability of buttons that change wording while you hover over them? I've tried [A, B, and C], but so far, no luck." This shows you have at least done your homework and tried several things, and that you know the area you want to have them focus on and that it's a specific question. Under those circumstances, most developers are more than happy to help you get unstuck. If you are not prepared, or you seem unfocused in your questions, that's a lot harder for them to understand what you mean, and repeated requests will get a less than enthusiastic response back.


- Singers often fell prey to being under the influence of "L.S.D." back in my performing days. LSD in this case means "Lead Singer Disease". It's where they are so excited to be performing and getting involved in the process that they sometimes forget they are part of a band. When we get involved in the broader community of testing, whether that be speaking, writing, seminars, etc., we also can get very excited about the process, and forget that there's a company that's paying for us to do our day job.  When it's something like music and testing, it's easy to separate the two. When we are doing testing in our day job and writing about testing or doing seminars on testing in our off time, the lines do definitely blur. In this case, it's very important to know where one sphere ends and another begins, and while keeping them totally separate may be counter productive, you don't want to have to say that your testing is suffering because you are stressing over your talk you'll be giving at a local testing meetup. If it helps, think of being a musician in an original band and in a cover band. Yes, you're still playing music, but you have two gigs with two different requirements. Remember to sing the covers with the cover band and the originals with the originals band. Otherwise, it can get awkward ;).


So that's it... for now at least. Our riverboat ride is at its end. Of course, I hope to have many more years of software testing to examine and consider, and it's possible I may revisit this series each year to reflect on what I've learned and what you might find interesting as well. Until then, be well, and thank you for joining me on this journey.

Saturday, January 28, 2012

Into the Blue: A Meandering Walk Through Twenty Years of Software Testing

In some ways, October of 2009 feels like just yesterday. In others, it feels like a lifetime ago. I liken this period of time to my stretch from May 11th, 2003 until February 25th, 2005. Back then I went back to school full time to complete a Bachelor’s Degree and set myself up to work full time, go to school full time and be a dad, husband, Scout leader and competitive snowboarder (well, OK, I used to compete… saying I was competitive might be a stretch ;) ). That period of time proved something to me. It proved that I had a capacity of doing a tremendous amount of work without it killing me. My going back to school was treated like a “youthful obsession” and its level of commitment was almost, well, obsessive.


A funny thing happens when you embrace your obsessions. You give a little, and you get feedback, and it excites you, and then you want to know more and do more and get more involved and practice more and get more involved until you are literally buzzing with the intensity. That “buzzing” was how I knew that I was channeling an obsessive energy and that I was “getting into something”. The blessing of being ADHD and knowing when these “fixations” are coming to the fore helped me then. I decided to try that experiment again, and see if I could “obsessify” myself as I used to in the days of my youth, and make software testing the target of my focus.


For those not familiar with ADHD, this is often not something you can pull off. Most people find that they are obsessing on something, and then they figure out if they can channel it. It’s the old joke that it’s ironic that the rain falls after you wash your car, but the reverse doesn’t work. You typically don’t wash your car in the hope that it’s going to rain. But that’s exactly what I wanted to do. I wanted to immerse myself into software testing and see if I could cause an obsession to develop. Thus, I had to find a way to carry it with me all the time. Did that mean a stack of books? Well, I had one testing book, and that was “Testing Computer Software”. I went back to reread it and while I found it helpful, it also felt very dated. It reminded me of my days at Cisco, and while I used many of the ideas back then, there were many things that I never read because they were not relevant to what I was doing (or so I thought at the time).


Lugging around TCS everywhere though felt cumbersome, and it made me ask a fateful question… are there any audio books related to software testing? I searched, and while, no, there weren’t at the time, there were some software testing podcasts that had been recorded a couple of years earlier. I downloaded all of them on to my MP3 player and they became my permanent companion in my spare time. Thus, I need to give credit to Randy Rice and his Software Quality Podcast for being the “tinder” that helped me start to set up what would become a roaring fire. Naturally, after listening to Randy and the various people he interviewed, as well as discussing test tools and actual effective ways of using them, I started to see a different way of thinking about testing. I also saw that what I thought I knew was actually fairly superficial, and that there were many more perspectives.


About this time, I saw that my library had a Safari Books Online Subscription, and through that, I had the ability to explore a number of different books. Some of them were specific to given code challenges I was looking at the time, but some were general testing related, as I read through them, I saw that there was a lot of information specific to the ISTQB and getting certified as a tester. While I looked through a few of these books, I didn’t see anything that specifically jumped out to me as a better way of doing testing, or should I say, there didn’t seem to be anything that went beyond what Randy had already discussed in many of his podcasts. As I was exploring a bit, I came across a book from a name I had seen in the magazines and recognized. Actually, it was the fact that it was not a testing book that first caught my attention. It was James Bach's “Secrets of a Buccaneer Scholar”, and the title alone made me fascinated to want to learn more. I bought the book, read through it, and found so much to relate to in my own experiences and my own “obsession based learning”. I always thought it was weird and strange and not at all a disciplined way to learn something. It felt great to see that there was someone else saying “your brain is a unique organism, an what works for me may not work for you, and that’s OK. What matters is finding what does work for you and them pimping the living daylights out of it” (OK, so James didn’t really say that, but that’s what I took from it).


So we had Randy to give me a daily drip of testing inspiration, and James to re-examine ways to inspire my actual learning and methods of learning. The next “person” to fall into the sphere of motivating me (and that’s appropriate because it was the aspects of motivation that I was looking for), went to Merlin Mann and his 43 Folders podcasts. I was initially going to try to implement 43 Folders as a Get Things Done methodology, but I actually never did. Instead, I became much more interested in the ways that Merlin encouraged time and attention, and understanding why you do things and why you don’t. Additionally, I valued something Merlin said on one of his podcasts early on (I’m paraphrasing here) “I don’t do these things because I’m good at them. I do these things because I’m actually pretty lousy at them.” So now we have Randy providing tinder, James providing the kindling, and Merlin giving me some big wood blocks to burn. Now all I needed was the match… and Seth Godin would prove to be that match.


As I was looking to understanding what and why I was trying to do what I could to learn more and get better at software testing, I heard repeated references to a new book that was being released. The book was called “Linchpin”, and its author was the aforementioned Seth Godin. Since I’d been getting much of my inspiration from the world of podcasting, I decided that getting the audio book version of Linchpin would be interesting. As many of you who have followed my blog now, I credit Seth with being the ultimate catalyst to getting TESTHEAD started. It’s more than that, though. Linchpin was the match that lit up everything for me. By itself it may not have done that, but in combination with the materials I’d listened to, pondered and internalized from Randy, James and Merlin, Seth’s book was the piece that set it all alight and started my trajectory from being on the ground and getting ready to soar into the blue.


What I ultimately got out of all of this was that I was waiting for someone to show me the way, to tell me what to do, and when I got that key piece of information, then I’d be ready to be awesome. Truth be told, though, that’s not the way to become awesome. If someone can tell you how to be awesome, then you aren’t going to be. It sounds counter-intuitive, but work with me here. People who make break-throughs don’t follow the road map. They question it. They ask different questions. They approach it from another angle, or several other angles. They don’t do what they are told, but rather, they forge their own way to their understanding.


Back when I was a musician, I had influences that spanned many different musical genres. Yes, I was a fan of Kiss, but I was also a fan of Earth, Wind and Fire, of David Bowie, of The Jam, of Prince, of Metallica, of Oingo Boingo, of the Cure and of Bauhaus, of the Sisters of Mercy and The Mission. I auditioned for a lot of bands that were looking to fit a particular mold. They wanted someone who sounded like Bon Scott of AC/DC, or they wanted someone who sounded like Seven Tyler of Aerosmith. They were looking for someone who fit the blueprint of what they expected a rock singer to be. I came from a much different place, in that, while I loved singing hard rock, and it was a range that worked well for my voice, my personal influences came from a very different place. Thus, when I wrote or when I sang, I didn’t sound like the other singers. Superficially, I did, of course. I had the gravelly style with the ability to sing high and cover a broad range, but my voice didn’t sound like Steven Tyler or like Bon Scott. Nor did I want it to. I wanted it to sound like me. Interestingly, years later, when someone did do an analysis of my voice, they said I sounded like what would happen if Jon Bon Jovi, Paul Stanley and Adam Ant were fused together. I thought that was kind of cool, in a way, that different styles from my own experience blended to make a somewhat unique voice. That was my success, not that I followed someone else’s blueprint, but that I started to forge my own from all of my influences, and then made a brand around it.


This brings me to March of 2010, and the start of TESTHEAD. As I looked back at the initial posts, they are all written in that tentative, just getting started, trying to say the right things to get noticed and be taken seriously way. In short, it mirrored my initial attempts to start a band. I mimicked a number of other people at first, until I started to have unique and interesting experiences of my own. From there, I could see my own style developing, including injecting my own humanity into the process. Just like when a musician writes songs that are abstract and more or less copies of other people’s songs, they may get a nod of appreciation, but they don’t really connect with an audience. That connection gets made a lot easier when the songwriter puts their own world into their songs and puts themselves into the songs. Likewise, I saw that I was doing the same thing with TESTHEAD. Sharing my thoughts, my insecurities, my successes and my failures made the ideas I was exploring much more real. Now it wasn’t just a matter of talking about a test technique, it was putting myself in the middle of it and working through what I understood and, often more telling, what I didn’t.


Actions cause reactions, an when you are in a band, you learn about other bands, and you oftentimes look forward to playing on the same bill with them. Doing so gives you a fun experience, but it also gives you a little desire to “show the other bands up”. Done correctly, with a spirit of fun and entertainment, there is nothing at all wrong with that. Playing to an audience should be entertaining, and you should want to put on the best show possible. Ripping off another band’s act to do so is not cool, but honing your own show to be the best it can be is totally OK. Testing is much the same way. We interact with many different people, and we rub shoulders with them and learn from them. While I don’t particularly look to “steal” someone elses’s ideas and present them as my own, there is no question that I spend a lot of time trying to understand how various people approach a problem, and learn what I can from them, and incorporate what makes sense to me into what I do. To that level, a lot of what many other testers have done has made their way into my testing approach.


What was interesting to me was that, when all was said and done, I’d managed to do something I didn’t think was possible. I threw myself into a process and a goal with the hope of sparking an obsession, and in a way, that’s exactly what happened. I also modeled my experience on my time as a musician, and I took lessons I learned from that time to help me do this. When I compare being a music Rock Star to endeavoring to be a testing Rock Star, I do it because there are definite parallels. When a musician promotes and markets themselves, they can develop a following and demonstrate expertise to where others will take interest and share that knowledge with others. The same goes with our testing experiences. When we can communicate something that resonates with others, we can help them do better in what they do as well, and in turn, that helps build word of mouth of our own brand.


Since there was a great deal of influence on me from the world of podcasting, and since I saw how that medium had a tremendous effect on me personally, I was really excited when Matt Heusser put out a call to help him with a new podcast initiative he was working on. As most readers already know, the TWiST podcast has been an active part of my testing journey over the past year and a half, and getting the chance to listen to and shape the shows each week, I have had the chance to learn from many different sources and really explore their thoughts and ideas. For every half an hour show that we produce. I would often spend four hours or more going over every word of the show to edit it to the right length, and that gave me a lot of time to let the ideas sink in and percolate. Each of these ideas gave me a chance to try out the ideas for myself, see if they worked, and give me something to write about.


A blog is, in a way, institutional memory. So much of what I’ve written has covered a lot of ground, and has allowed me to formulate my own style and ideas. That writing has allowed me to branch out into other areas such as conference presentations, guest blog postings, and even writing a chapter for a book. Like so many other things, action gets a reaction, and enthusiasm for doing something encourages others to engage because most people just consume (that’s not a dig, it’s just a fact). Most of us in so many things will be happy to consume. We love to read, but far fewer of us will ever write a book. We love to listen to music, but again, far fewer of us will ever join a band and write songs for other people to listen to. We may love and appreciate art, but far fewer of us will actually put in the time to learn how to become exceptional artists. Yet if we actually do put ourselves out there and try to do these things, people will come and get involved with us. It’s a natural reaction. So it is with testing. If we put ourselves out and say “we want to explore this” there will be many to give us a hand. That’s been my experience, in any event.



All of this happened within the space of a year, and my friends and co-workers at Tracker definitely noticed the difference. They saw that my level of engagement and interest had grown tremendously, and hat I was once again excited, no, borderline obsessed with testing and learning about testing. Throw in the opportunities that developed with becoming part of the Miagi-do School of Software Testing, joining the Association for Software Testing, taking the Black Box Software Testing classes, teaching the Black Box Software Testing classes, getting involved with Weekend Testing, and all the while using tools like Twitter, LinkedIn and Facebook to share the conversation with others, an discover others who wanted to share that conversation.


One of the benefits of being so open about sharing that information is that, when you are doing so, someone may be watching. Granted, most people may be amused, annoyed, or just plain confused about what you are doing, but someone else in another place may be paying attention, and when a question comes up, such as “hey, our team is looking for a software tester, so you know who might be a good fit?”, they may well say "as a matter of fact, yes!" I mention this because that is exactly what happened in October of 2010. And old friend and co-worker contacted me and said “hey, I can’t help but noticed how involved you are with software testing. We’re in the process of looking for software testers, and while I doubt you’d be interested, we’d love to talk with you about what we should look for”. That conversation branched into several others, and at the end, resulted in me being asked if I would consider taking on a new role as a senior tester at SideReel. Not only did I consider it, I accepted it. When I told my friends at Tracker about the opportunity, they encouraged me to do it. They would be sad to see me go, but also understood that it was a great opportunity and that I had worked really hard to be ready to take it on. Thus, after six years of a tight knit family, I would leave and go forth and explore another opportunity with another small group. Of course, their time as a “small group” would be short lived, so to speak, but that’s part of the next and final installment :).


So what came out of all this?


- Inspiration comes from many places. I cannot pinpoint just one person or say “it was THIS that changed everything”, actually, it was a lot of small incremental things that came together that made for the change to take place. We may sometimes have the ability to do something extraordinary in one fell swoop, but usually it’s more like a snowball hat we pack a little snow on and roll down a hill. As it collects more snow it gets bigger and bigger, and very quickly, but it still starts from small actions.


- Every person is a brand in one way or another. We are always marketing ourselves, even if we don’t realize it. TESTHEAD is my brand, and it’s the way that I show the world what I do and what I believe about what I do. It doesn’t tell the whole story, but it definitely gives you enough of an idea who I am and what I do to make some conclusions. Some people may want to know more about me because of this blog, maybe even hire me some day. Some may have made up their mind that they will NEVER hire me after reading this blog (LOL!)… and that’s totally OK. At least this way they know what they are getting, or not getting.


- A blog is an open portal. People are free to come here and take my ideas and call them their own. I have a copyright and a statement that I would appreciate links back and attribution, but I realize that people the world over may well “steal” my ideas or copy my stuff for themselves and present them as their own. I don’t have a problem with that because I’m not my blog. It’s a repository of my memories and experiences, but it’s not me. I’m the ideas behind the blog, and I’d like to believe that I have a whole lot more where that came from. Time will tell if that is true.


- People pay attention to what you post, even when you think no one is. I have found it interesting to hear people talk about things I wrote a years ago and I’d say to myself “wow, I didn’t think anyone had read that!” Just because people don’t comment, doesn’t mean they aren’t reading. Also, don’t be at all surprised if your next interview or job offer comes from someone who has read what you have written. They have also seen that your blog is not you, but the ideas that make it. They want to know more about those ideas.


- Put yourself into you material. Regurgitating facts and figures is boring and many other sites already do that. Your experiences and your understanding of the experiences are what makes the information valuable… at least if my own reader stats and comments are any indication.


- We are not born with ideas, we all “stand on the shoulders of giants”. I often lament that I have not developed some “great idea” or introduced the “next big thing” in software testing, but really, who has? For the most part, we are dealing with variations on themes that have existed since the time of Socrates. There is little “new” under the sun, but there are lots of new ways to see the world we are already familiar with, and those discoveries are almost always personal. Those break through and “a-ha moments only come when we put our time and attention to the problems we have here an now.


- The only way to become a master at something is to do it, a lot, with great focus and energy. The Malcolm Gladwell Outliers formula of 10,000 hours to become an expert at something is legitimate and valid. If you spend an hour a day, you’ll be come an expert in 27 years. If you do it 24 hours a day, you could become an “expert” in a little over a year, but no one does anything except breathing for 24 hours a day, and suffice it to say you are already an expert at that. Expertise takes time, it takes practice, and it takes dedication. The more time you spend, the more expertise you develop… and no one is born an expert at anything… well, except for that breathing thing, and even then, we still had to learn it at our births.