Friday, December 30, 2011

Exercise 40: Dictionaries, Oh Lovely Dictionaries: Learn Ruby the Hard Way: Practicum

All right! We're getting into something that I've seen a lot in our data outputs on the console when I am debugging our applications, and I've long wondered what I was looking at. This exercise takes that on. This one is all about hashes. What's a hash, you say? Well, read on :).

Ruby calls them "hashes", other languages call them, "dictionaries".  Zed says he uses both names, but what they are called doesn't really matter. What does matter is what they do when compared to arrays.

An array lets you do this:

Arrays store their values in an ordered list, and you can reference and access those values by calling the index number from 0 to, well, whatever the last element in the array happens to be, and whatever that number is.

A hash works similarly, but you don't have to use numbers to access the elements stored in a hash. You can use anything. Here's an example:

[For the record, the example on the LRtHW site has a back slash for the multiplication sign. This doesn't work on my environments; both Ruby 1.8.7 and 1.9.2 give me an error. Removing the back slash works as expected. See below. I also let Zed and Rob know about this, so this may well be fixed by the time this entry appears...  and has been :) ]

Instead of using numbers, we are using "symbols", which are effectively name tags, an they are easier to remember than trying to figure out where in an array something is.

Here's another way to do it.

So that's kinda cool, I can insert new items and give them a unique id and then if I print out the hash, I can see where it fits along with the number or id.

Hashes also let you delete stuff, too:

So here's the exercise for this go around, in case the previous wasn't enough to bring the point home :):

What You Should See

Extra Credit

Go find the Ruby documentation for hashes and try to do even more things to them.

[There's a lot of stuff here! hash has a bunch of method options, most of which I'm just barely able to understand how I would use. For grins I played with merge, which allows the user to take two separate hashes and merge them together. Interestingly, if the second hash has a pair with a key that matches the first one, it's the second hash's value of the pair that will be used. See below.]

Find out what you can't do with hashes. A big one is that they do not have order, so try playing with that.

[ This is correct. They go in as you create them, and they get listed as they are ordered. the one difference is that, if you merge two hashes, then the location of the original hash key and value is replaced with the new value, but its ordering in the hash is preserved.]


This is cool, it's an item I can definitely see using for an application like a phone book or contact lookup. I'm sure it can be used for a lot more than that, and I look forward to more options I can use going forward. What I like about it is the fact that the key can be an actual word, which is a lot more logical way to consider doing a lookup compared to remembering or finding a number in an array.

Thursday, December 29, 2011

Opening Up New Possibilities

The Salvation Army Truck Came, and They Took the Beautiful Monster Away...

sounds like the opening line of The Dream Academy's "Life in a Northern Town".

In a way, I feel a little misty today. While just a couple of days ago, I said I was fine with my decision to let the giant walnut computer hutch go, we are often reminded of setting things up, having everything that used to be there, and now it's definitely gone. A friend of mine pointed out to me that it's like having a friend move away. We may not have done much together lately, we may not have talked on the phone all that often recently, but we always knew we were there, until the day that they call you and tell you they've accepted a job back east. You're happy for them, and they go on to do bigger and better, or at least different, things, but suddenly you realize... they are gone. The Beautiful Monster feels a little like that.

The funny thing when you make a change and suddenly have a lot of fresh options is to think "wow, what am I going to do with all of this space?!" For grins today, I grabbed a folding table and sat down with my two laptops, and started thinking of how I would set everything up. What happened? I realized that I was putting everything back into place, just as though the Beautiful Monster was still there. Hang on... if I'm just going to do the same things I've always done, what was the point in giving the computer hutch away?  This is a chance to do something different, to really change up how I do things. Again, the question I asked originally came back into my head... do I really need to have a dedicated home office? With the work that I do now, and the way that I do it, is there really a benefit to having the room permanently set up this way? Are there other things I want to do with this room? I realized that there were lots of things I wanted to be able to do, and if I set everything up exactly the same way, then I couldn't do them. This got me thinking as to the need to keep so many of the things that I've always taken for granted. Why are they there? What purpose do they serve? Well, I have to have a bookshelf... or do I? It's fun and dangerous when you start down these roads :).

What I found as I thumbed through many of my cherished technology books is that most of them are grossly out of date. I have newer versions of them in PDF format or I have access to sites that cover the same material, often better. I had a book about Tcl/Tk. Cool language, neat framework, I haven't used it in over 12 years, though, and the entire reference is available online should I need it. To what benefit is me keeping an 18 year old book around going to accomplish? Other titles fell into that same category, and I realized that many of the books I had on my shelves were long outdated. Thus, new goal, focus on evergreen books as keepers and references, and liberate titles that will serve no purpose to me or my family any longer.

This is an interesting exercise, because it really shows what things you value and want to keep. I ended up with a shelf of CDs, a shelf of DVD's related to Korean Drama, some random movies, and Native American handicraft and tradition. Another shelf is "evergreen how-to guides". Think things like  sewing, money management, home repair, camping, guitar and playing music, gardening, fitness, Japanese language study and stuff related to Native American handicraft that would be hard to find anyplace else, Another shelf is dedicated to fiction and literature that I enjoy from odd places. Everything from Homer, Cicero, Jane Austen, Orson Scott Card, Stephen King and other titles that I go through semi-regularly.  This also includes my full run of of the manga of Neon Genesis Evangelion and my much beloved volumes of the Elfquest saga. Another shelf has what I call my "business and critical knowledge" shelf, which contains a number of books from various disciplines, including a few timeless titles related to writing. Examples include my much used copy of the Little Brown Handbook, Stephen King's "On Writing", Twyla Tharp's "The Creative Habit", Steven Covey's "The 7 Habits of Highly Effective People" and "Principle Centered Leadership", James Bach's "Secrets of a Buccaneer Scholar", and a number of books given to me to review and I have decided were worth keeping as permanent references related to testing and data security. I was surprised that this wasn't a much larger list, until I realized that most of my current reading on these topics is in electronic format.

I have two sentimental holdovers that I was not willing to do away with. The first is a near complete collection of mental_floss magazine. I have all but three issues dating back to first publication to today, and I keep all of them. The second is a shelf full of classic black bound books from The Nobel Library. These books were a treasure to my grandmother, and she would often talk about stories she read in them and some of the interesting authors she discovered. The books covered the authors who won the  Nobel Prize for Literature from its inception on up to 1970 when the volumes were printed, and the pieces of literature that actually won the prize in that given year. When she passed away in 2001, that was one of the few things of hers I wanted to keep. It helped keep a connection of a love of reading and being willing to look for new knowledge and interesting stories wherever they might be found, and to appreciate the different voices and viewpoints in the world.

Several books that didn't make the cut are still in excellent condition, so I'm going to be bringing them to my local library. Some have been discarded as they are very much out of date or no longer relevant. What I kept says a lot about me personally... it also says I won't be getting rid of or downsizing my current bookshelf after all (though I've made some space for some new acquisitions :) ).

As I pointed out in yesterday's entry, I don't believe in New Year's Resolutions, but I do take stock in what I've done during the year and what I've held on to, and what I feel should be gotten rid of or left to find a new home. What comes and goes isn't as interesting as what stays year after year. The things that endure are often not the things we think will endure, and the stuff that we put a lot of attention into at one point in time often becomes out dated and useless to us later on.

Oh, and about that table... I decided to fold it up and stick it under my futon. An additional short term goal for the next few weeks is to only break it out when I physically need a desk to sit at for a needed period. and then to fold it up and put it back away. I'm going to dare to be bold for a while, and allow myself to picture living with and having this open space, and not be in such a hurry to fill it with old habits. New possibilities, after all, can only make themselves manifest if they are given room to be seen :).

Wednesday, December 28, 2011

Chain... Keeps Goals Together

We're homing in on the end of the year, and many are abuzz with the "New Years Resolution" virus. For those curious, I never make New Year's Resolutions. Well, OK, I used to make them when I was younger, but I gave up when I realized that I was more times than not just setting myself up for failure. I realized something several years ago. Resolutions are weak willed things, and they are easy to break. Specific goals, with detailed and measurable progress points, are much more likely to lead to success.

Unlike resolutions, I believe wholeheartedly in setting regular goals, and I believe in setting small ones. Things I can work on for a given day, week, month, etc. Big, life-changing goals are good, and occasionally, there is a specific incentive to take on one of those big massive goals, but most of the time, the human constitution just can't wrap its head around a massive life-altering change. At least not in big extended chunks. Let's take an example of losing weight. It's a popular New Year's Resolution topic.

  • "I'm going to lose 50 pounds!"
  • "I'm going to work out every day!"
  • "I'm going to give up all processed foods!"

These are classic weight related resolutions, and more times than not, they are scrapped in a rapid order, often within two weeks. Why? Because they give an impression of being specific, but they aren't. They are very nebulous, with the exception of the "losing 50 pounds". Could be a great goal, but how will you go about doing it? How long will you allow yourself? and what will you do once you get there? The truth is, most long term goals are notoriously unfinished, because we don't really give ourselves realistic parameters.

I'm much more a fan of making very specific small and short term goals, and along with the goals, charting my progress with "chains". I love chains! It's an idea I got from an old Lifehacker piece called "Jerry Seinfeld's Productivity Secret". In a  nutshell, the idea is to take a goal, and when you do something related to that goal, mark it on a wall calendar that displays a full year. Each day you do something towards your goal, write down a mark with a red pen, and after doing it multiple days, make a chain. From there, don't break the chain.

What's great about this advice is that is emphasizes consistency and regular practice of whatever it is you are doing. Jerry Seinfeld used this to meet a writing goal. The same could be used for reading, for exercise, for cessation of a bad habit, or practicing a musical instrument. Whatever the goal, start a  chain and make small links to keep building the chain.

Having said all this, you may be wondering what some of my "chains" are. Glad you asked. Some of them I have kept in a focused manner and have some long ones. Some others are collections of short chains interrupted here and there. The col thing is that, if you can create a lot of little chains, even if they are separated by a day here and there, you will still have a hefty chunk of chains to look back on, and likely a lot of accomplished goals to go with them. Learn Ruby the Hard Way is a chain. Any BOOK CLUB synopsis I do is a chain. My 10 a day SET practice is a chain (I use it as a drill to see how quickly I can recognize patterns and if I am getting faster at seeing them). So what are my "goals" that I want to focus on in 2012? Here's a basic list.

* Complete Learn Ruby the Hard Way synopsis and then move on to other Hard Way projects.
* Commit to a once-per-month, 1st Saturday unless impossible to attend Weekend Testing Americas Schedule.
* Get back into the swing of doing a book review each week.
* Work through my stack of Ruby and Rails books, and create more Practicum entries
* Curate and mark-up TESTHEAD, so that topics that are related link posts.
* Go through and do editorial on TESTHEAD, correcting spelling mistakes and grammatical faux pas' (I already know there's an embarrassing amount of them).
* Focus more on topics specific to advances in coding and automation.
* Declutter and dejunk my home and work area.
* Focus on opportunities to develop presentation of testing experience and ideas; create a back log of talk and seminar material.

That's plenty to keep me busy this year, and there's enough variety in there to keep me busy for, well, many years going forward. Tackling them all simultaneously and with 100% focus would be impractical and likely to fail. But doing one or two at a time, and chaining the small bits I can do each day, as well as staggering the ones I do at a given time, will help me approach many of these goals. A small step each day on the ones I want to see move forward will help me keep moving. If I get bogged down on one, I have many more to jump off to. Yes, SMART goals are good, and yes, being realistic in expectations is also good. Above all of these, though, is the commitment to a little bit each day where you can, and when and where possible, do not break the chain :).

Exercise 39: Doing Things To Arrays: Learn Ruby the Hard Way: Practicum

This time it's back to the future, or more specifically, back to arrays and considering some of the things that we can do with them now that we have tools like loops to help us work with them.

One of the things that arrays allow us to do is to "push" items onto them and "pop" them off. This hearkens back to C programming for me and using UNIX to "push and pop" items off of a stack. I sort of got what that was all about, but it's been awhile, so it's good to get the chance to see how Ruby handles this, and give me a chance to re-explore this approach (and maybe learn it for real this time :) ).

Zed explains that the approach to pushing an item onto an array covers a number of steps.

Let's use this example: mystuff.push('hello')

1. Ruby looks up the mystuff variable. From there it determines what kind of variable mystuff is (a function call? A global variable?), In this case, Ruby finds it and sees that it is indeed an array.

2. Next, it sees the period ('.'). This keys the Ruby interpreter  to start looking at possible functions (methods) associated with this variable (in this case, an array).

3. When it sees "push" in the variable name. Ruby checks to see if that is a viable and legitimate function (which it is), and prepares to use it.

4. The '( )' (parentheses) let the Ruby interpreter know that what follows is a function call of some kind, and that the value inside of the parentheses is any number of arguments, depending on the function being used (in this case, the string 'hello').

5. Finally, when it reaches the end of the variable value, with all of its methods and function calls, it then executes that step in the code.

So yeah, that's a lot of stuff to consider, and that's all with just that simple statement.

All right, let's check out the code for this exercise and see if we understand what's happening.

 And here is what we see:

Extra Credit

Go read about "Object Oriented Programming" online. Confused? Yeah I was too. Do not worry. You will learn enough to be dangerous, and you can slowly learn more later. Read up on what a "class" is in Ruby. Do not read about how other languages use the word "class". That will only mess you up.

[Yep, this is something I've had a touch and go understanding of for years, much more touch than go. Generically, I get it. There are objects, and there are ways we can interact with those objects. We can use and reuse objects, we can create whole libraries of simple objects that we can call on as we need them. that much I get. In the Ruby world, a class is a top level object that can have its own methods defined. If we want to make something new in Ruby, we define it as a class, and then we create methods to interact with that class. as long as we name it something that doesn't conflict with a dedicated Ruby keyword, we're clear. Classes are also able to have their own scope and their own variable space, like any function. Classes can also create functions and nest those functions. Functions can also be sub-categorized, and those can be subcategorized even more. When we see something like Class.method.sub-method.sub-sub-method('argument'), each period shows that we are calling a function that resides within that given function.]

What's the relationship between something.methods and the "class" of something?
If you do not have any idea what I'm talking about do not worry. Programmers like to feel smart so they invented Object Oriented Programming, named it OOP, and then used it way too much. If you think that's hard, you should try to use "functional programming".

[I think I explained that above :). ]


The ability to loop and iterate with arrays, and to have tools that allow us to ad and remove items from an array is very powerful when it comes to processing text. This is how UNIX systems do things like grep and sort and awk, etc. It's cool to see it in this manner, and with a language that feels less bulky, so that we can get a handle on what is actually happening. the ability to manipulate strings and arrays using functions as part of a class is also pretty cool. I expect I'll be working quite a bit more with classes over the ensuing few days.

Tuesday, December 27, 2011

"Break Throughs" Sometimes Require "Breaks With"

For the past decade plus, I have had a "beautiful monster" in what is effectively my home office. I say effectively because, in all reality, the Home office is really a place for a book case, a fold down futon/couch, my closet with my clothes and miscellaneous items for said futon (makes for a semi-nice guest bedroom in a pinch), but the dominating feature (and I used that word very literally), is the Computer Hutch/Armoire. It's a beautiful piece of walnut furniture, with six doors, an internal light, adjustable media shelf, places for CPUs, printer, scanner, external drives, filing drawer, and a retractable desk that can be folded in and closed up behind six panels. It's beautiful, and it's huge, as in 24 inches by 48 inches by 72 inches huge, and that's without the desk pulled out.

This was the first purchase I made for my "home office" in 1999. When we bought our house, I was overjoyed to finally have a room that was going to be my office. An actual room, not setting up in a side closet as in our previous place, not shunted out in the garage when I outgrew the closet and the heat from a SPARC station and a 21" CRT monitor became unbearable. This was going to be a real honest to goodness dedicated office, a veritable "man cave" of my very own, and to house the tons of bulky computer equipment I had at the time, including the said SPARC pizza box, 21" CRT monitor, and a secondary PC that was connected to the same monitor and keyboard, the armoire was ideal, along with a big executive chair and everything in its place.

Fast forward 12 years. The SPARC station and original PC CPU are long gone. They have been replaced a couple times. Today, my digital life and work reside on a Macbook Pro and a Toshiba Sattelite PC. The need for a dedicated printer is now in the family room where the entire family can use it. Network connections come via wi-fi. External storage is now more often than not in the cloud, with some DVD backup media for good measure. Future platforms are possibly looking to be tablets (whether iPad or some Android flavor) or smartphone (whether iPhone or Android). The simple fact is, the Armoire, while it looks nice, it's a relic now. It doesn't fit the way that I work any longer, but I've tried to force myself to  keep using it for years now. I paid a lot of money for it. I wanted to get my money's worth out of it.

The funny thing is, we often invest a lot of ourselves, our energy, and our emotions in items that are just plain and simple past their effective use life. Don't get me wrong, this desk will be a gem to someone with the room for it and who would like to have it serve a similar need (it has enough room for a big flat screen TV inside, plus the ability to be a fully functioning office desk if necessary. It's just that it no longer fits my life and needs any longer, and justification to keep it around just burns up cycles, not to mention my having to do clutter control of a major scale just to keep the area around it tidy.

Today, I made a decision. I called my local Salvation Army store and said I had a great piece of furniture looking for a new home. They'll be coming by later this week to pick it up and bring it to their showroom. In return, I will have 48 cubic feet of space to do something with. I may set up a card table or something to have a place to sit and type if I need to, or I may just leave the space empty and actually have the ability to walk into the room and sit down and breathe and relax. I may re-purpose the room entirely, who knows? The fact is, I can do my work anywhere now. I don't really need a dedicated office any longer, and I'm willing to bet that developments in the coming years will make the need for a dedicated space even less relevant (though I will probably need it as a quiet space to do show production for the foreseeable future).

At the end of this year, think about the tools, practices, policies or equipment that you have "invested in" and ask yourself, are these items, practices or policies genuinely useful to me, or do I keep them on life support just because I'm sort of attached to them? If you can say that you really do use them and they really bring value to what you do, then you'd be perfectly fine to leave things be and not do anything. However, if you find, like me, that you are spending a lot of energy producing "churn" for no other reason than to churn, give that process or item a lot of thought and see if you can live without it. If so, find a place to put it and get it out of your reality. If in truth, you can do just fine without it, let it go. Don't spend another minute letting it clutter up your time or your energies.

Have you wanted to learn a new language or use a new approach to testing, but you are hamstrung by the practices you have to keep up and maintain? If there isn't a real compelling reason to keep them going, dare to set them aside for awhile. Examine their real utility. You may be surprised that all of the attention you've been paying to "essential reports, forms, charts, and processes" might actually be not that essential after all. Dare to do something different, and see how it goes. Consolidate processes where it makes sense, and dare to stop doing some things altogether if you are really just treading water doing them. The end of the year is a classic time to de-junk, de-stress and de-clutter. Take the time to do so, and you may find that your house, your desk, your work group, and quite possibly your sanity function way better by removing the thing that you think you have to keep around, but really don't. Give it a try, let me know how it works for you :).

Exercise 38: Reading Code: Learn Ruby the Hard Way: Practicum

This exercise requires us to go out and find someone else's code and see if we can make sense of what we see. What I found was that, in most cases, there is little in the way of completely self contained projects. Most of the projects that are out there rely on other gems or other elements that have already been developed somewhere else. While this is an effective and contained way to pull in functionality, it can be frustrating to try and find where the actual files are.

I decided to take a look at a project called "shoulda" which is a testing framework along the lines of Cucumber. What I found while going through "shoulda" is that shoulda is a meta project, and that the actual work is being done in two other projects, shoulda-context and shoulda-matchers.

Right now, my goal is to check and see what I can understand from what I am reading, and what I cannot. As I was looking through a number of the files, I found some things that were easy to understand and made sense of the first run, and I found some other things that, while I didn't quite get how they were being implemented, I understood their context and what they were doing. Case in point, there is a "usage" function. It prints out what is not meeting the requirements and then shows a boilerplate text of how the application should be used.

While a lot of the specific implementation details are still fuzzy, I've found that by going through the files themselves and just stepping through the modules and functions as they are defined, I can understand a lot of what the application is doing. Some of the stuff is still over my head (mainly because there's a few areas I've yet to focus on) but much of the details are not so foreign now.

As was made clear in the last exercise, just going through and defining the majority of the keywords, operators and flow control options made a big difference. It has helped me to see that many of the terms that are used in code that I'm unsure of are actually defined someplace else, and usually are not too hard to find once you track down and follow the require statements in key files.

The areas that I am actually still finding myself having more trouble with are the specific methods that are allowed with a given object. the good news is that, in most cases I've seen so far, these methods are generally well explained if their root objects are easy to get to and understand.


Each time I think "yeah, I've got this down", I'm finding that there's still a lot more to learn when I read someone else's git repository (or check out our own projects that we run in our test environment). My own "simple" scripts that I keep track of on my automation environment use a lot of different gems and projects, and I find that many of the statements used in Cucumber, for example, some are specific to RSpec, some use Capybara nomenclature, and some use things that point to technologies and projects I have little understanding of.

On one end, it's helpful in that a lot of the details have already been put together for me, and I just use the steps that make sense and I don't have to do a lot of tweaking. On the other hand, this raises new frustrations, in that if you need to make a change or edit something to work in a different way, you may strike it lucky making a change, but you are not 100% sure that you understand where that change has impact.

For me, certainly, I've found that a change that worked in one instance didn't work so well in another, and I was hard pressed to understand why. This is where being able to track all of the dependencies in a project, and what code and "flavors" of interaction they produce can help a lot.

Thursday, December 22, 2011

Into the Blue Again...

It's amazing to think that 2011 is almost over, and yes, while last year I lamented writing the obligatory "year that was" letters and somewhat lampooned them with my post last year titled "Well, How Did I Get Here?", that post resonated with many people. It is to date my most read and my most commented on article here on TESTHEAD, depending on which metrics you believe.  Based on the response to that post, I decided this year to just let it be known, this is a recap of the World of TESTHEAD, and the world of "Michael Larsen, Tester" for the year of 2011. The title this year is indeed, again, in homage to the seminal 1980 Talking Heads classic "Once in a Lifetime".

2011 was a year of transition for me personally. I took many leaps of faith this year, and as the title says, I willingly jumped into new areas and new responsibilities. Early in the year, I ended my employment with Tracker Corp, bringing to an end six years of learning, camaraderie and a focus on the .NET world of software development and testing. In exchange, I came to Sidereel, and a world of learning, camaraderie and Rails software development. This is telling, because I'd never worked with Rails before, and my involvement with Ruby prior had been from recommendations from co-workers that it would be fun to learn. Well, now it was more than "fun to learn", it was an occupational hazard (and necessity :) ).

With that, I started mapping out and learning a new site, a new programming language, a new model, a new way of storing data, and very different approach to developing software. I was no longer just a tester, I was to integrate with a fully Agile development team and work with and alongside of them. Oh, and I traded in a daily diet of Windows and PC's for a daily diet of Mac OS X and Darwin UNIX all sleekly wrapped in a Macbook Pro. Oh UNIX, how I have missed you!!! There  was just something comforting about leaving behind the world of MSI and EXE files and embracing tools such as ruby gems, homebrew and other options for installing software. Scriptable, customizable, and where Test Driven Development and Continuous Integration were not obscure buzzwords but actual practices that were, well, practiced! It's also been telling, humbling, and intriguing to learn about and use tools like Ruby, RSpec, Cucumber, Capybara, Selenium Web Driver and other areas of automating testing. I can safely say I have written more code this year than I have in the past 17 years prior!

2011 also saw the process of Weekend Testers Americas come into its own. What could have been a few experimental and jerky first few sessions got smoother, cleaner, and better understood, and we had some great successes during the year. While I'm not sure how much others have learned, I know that I learned a great deal from this process. What was great to see was that this initiative was embraced by people all over the world, and our participants reflected this fact, including testers who would come into our sessions at 12:30 AM (yes, after midnight) from India to participate. First off, that's dedication, and my hats off to everyone who did that, but more to the point, it spoke volumes about the service we were offering and the fact that people wanted to come in and participate, even at those insane hours. We had some help from some heavy hitters, too. Michael Bolton and James Bach both came in to guest host some of our sessions ("Domain Testing" and "Creating Testing Charters"), and Jonathan Bach helped me craft one of my breakaway favorite test ideas of this year, that of "Testing Vacations". In all, it was a banner year for Weekend Testing Americas, and I am so thankful for all of the participants that helped make it possible. I'm especially thankful for Albert Gareev, who in addition to being a regular participant, stepped up to become my partner in crime for this enterprise, and frequently helping me develop new ideas or take the process in different directions than I probably would have had I been left to my own devices.

2011 was a year of meeting and developing relationships with other testers. In January, I met Matt Heusser in person for the first time. As many of you know, one of my most involved and enduring professional relationships was with (and continues to be with) Matt. I produce the "This Week in Software Testing" podcast with him. I helped write a chapter for a book he was the principal editor for (more on that in a bit). I also was a sounding board for other ideas and offered several of my own in return. I had a chance to meet my fellow Weekend Testing Compatriots Marlena Compton, Markus Gaertner, and Ajay Balamurugadas in various places. Marlena and I had the pleasure of live blogging the entirety of the Selenium Conference from San Francisco, with our comments getting us branded as the "Table of Trouble" from the other participants. That was a fun memory, and it helped to set the stage for liveblogging other events throughout the year. Geting the chance to meet so many testers during this year in various capacities was a real highlight and much enjoyed aspect.

2011 also saw my commitment to being published. I made a decision that I wanted to write beyond the scope of TESTHEAD. As will probably come as no surprise, my first few articles were Weekend Testing based. However, I had the opportunity to venture into other topics as well, including two cover stories for ST& QA magazine; one being my article about "Being the Lone Tester" and another an excerpt of my chapter from "How to Reduce the Cost of Software Testing".  Speaking of that, 2011 saw me and 20 other authors get our names in print and become book authors. It was a pleasure to have the chance to write a chapter for "how to Reduce the Cost of Software Testing". A later development, one in which I, literally, just got word about and accepted, was a potential new book that discusses "The Best Writing in Software Testing". I have agreed to be a junior editor for this project, and we are aiming for a 2012 release of this title. In addition, I also published articles with sites like Techwell, the Testing Planet and Tea Time With Testers. As of now, I have eleven articles that have been published external to TESTHEAD, and it is my hope that I'll be able to write more in the coming years.

2010 was a first in that I attended my first testing conference. I made the commitment then that 2011 would be the year I would present at a testing conference. I received my opportunity to do exactly that. My first ever conference presentation was just 20 minutes, and it was at CAST 2011. I presented in the "Emerging Topics" track and discussed Stages of Team Development lessons I had learned from Scouting, and how they could apply to Testers. All in all, it went well, and even today, I still hear from people who said they appreciated the topic and liked my presentation. In addition, I also gave another full track session at CAST called Weekend Testing 3-D, where not only did i discuss how to facilitate Weekend Testing style sessions, we actually held a live session with participants from all over the world, and processed it in real time (this was the earlier mentioned "Testing Vacations" session that Jonathan Bach helped me develop. In addition, I proposed a track talk and paper for the Pacific Northwest Software Quality Conference titled "Delivering Quality One Weekend at a Time: Lessons Learned in Weekend Testing" and after writing the paper and  having it reviewed several times, received the nod to present it. However, fate struck, and I broke both bones in my lower leg (tibia and fibula), thus preventing me from delivering the talk (the organizers of PNSQC, however, still included my paper with the proceedings). Additionally, a friend who felt bad that I couldn't present at PNSQC forwarded my paper to Lee Copeland, the organizer of the STAR conferences. Lee liked the paper and asked if I'd be willing to present it at STAREast in April, 2012. I of course said YES! So I will get my chance to present this paper yet :)!

There is  no question that I learned a great deal from the TWiST podcast, both as a producer and as an active listener, but 2011 will be even more memorable in that I graduated from editing the show and as an occasional guest to being one of a handful of rotating regular contributors on the mic. It's been interesting to have people email me and say "hey, I heard your interview last week, that was a great show and a great topic, thanks for your comments and explanations". I thought it was especially cool when I had someone say that they felt that I'd make a great game show host (LOL!).

2011 saw my continued focus on working with the Miagi-do School of Software Testing. At CAST 2011, a number of us Miagi-do Ka, including Markus Gaertner, Ajay Balamurugadas, and Elena Hauser worked along with Matt Heusser at the CAST testing challenge. During that competition, I had the chance to show Matt and the other testers there what I was able to do, and due to that experience, Ajay, Elena and I were awarded our Black Belts. While the experience itself was great, it also came with the expectation that I be willing to mentor and teach other testers, an opportunity that I have gladly taken on and look forward to doing more of in 2012.

One of my most active projects for the year of 2011 was helping to teach the Black Box Software Testing courses for the Association for Software Testing. I had the opportunity this year to instruct, as either an Assistant or as a Lead Instructor, all three courses offered in the BBST series (Foundation, Bug Advocacy and we just completed the pilot program for Test Design on December 10th). I was in this capacity that I was also nominated to run for the Board of Directors for the Association For Software Testing. I never envisioned myself being a Director of anything, much less an international software testing organization! Still, someone in the organization felt I deserved a shot, and nominated me. What's more, someone else seconded it. Even more amazingly, a lot of people (perhaps many of you readers) thought I'd be a good fit for the position as well, since I was indeed elected to serve on the board. My two year term began in October. While daunting, it is also exciting to think that I may actually help shape the future of this organization in the coming years, and to help represent my fellow testers. Believe me, it's not something I take lightly.

Quite possibly the biggest "Into the Blue Again" moment of the year, though, happened at our first AST board meeting in October. It was at that meeting that Cem Kaner and Becky Fiedler announced their desire to have someone take over as the Chairman of Education Special Interest Group. While a part of me felt I was wholly inadequate for the task, another part of me felt that this was something essential and that it needed someone to spearhead it so that the education opportunities within the organization could be championed and further developed, while allowing Cem and Becky the opportunity to do what they really wanted to do, which was develop more and better testing courses. With that, I offered to chair the Education Special Interest Group. I'm not sure what was more surprising, the fact that I offered, or that the rest of the board took me up on it! Two years ago, Cem Kaner was a man whose books I had read and whose presence loomed large as a "testing guru" on high. The thought I would ever meet him seemed remote. The thought I'd actually take over for him and spearhead an initiative he championed never even crossed my mind!!! Still, that's what has happened, and I guess 2012 and beyond will tell us what I actually did with it. I'm hoping, and working towards doing, all I can to prove worthy and up to the task.

2011 was, really, a year where I took leaps of faith, lots of them, and discovered that I could do even more than I ever imagined I could. I've shared may of those journeys in TESTHEAD posts, and I thank each and every one of you who are actively reading this blog for your help in motivating me to take these leaps of faith. It's been another banner year for me, both in learning and opportunities. Overall, the experiences of the past year have given me confirmation that, if I were to jump "Into the Bue Again", that it would be a great chance to learn and grow, regardless of whether or not the outcome were necessarily successful, lucrative or advantageous. Granted, most of them have been, and those that haven't been, well, I'd like to think I failed quickly and early enough to learn from those experiences and correct my trajectory. Time will tell if that's true, of course. As in all things, there were many people that helped make 2011 a banner year for me.

Thanking a bunch of people is always fraught with danger, because invariably someone gets left out, and there have been hundreds of people who have been instrumental in making this a banner year for me. Still, there are many that stand out, so to that, my heartfelt thanks to Adam Yuret, Ajay Balamurugadas, Albert Gareev, Alex Forbes, Anne-Marie Charrett, Ashley Wilson, Becky Fiedler, Benjamin Yaroch, Bill Gilmore, Cem Kaner, James Bach, Janette Rovansek, Jason Huggins, Jon Bach, Lalitkumar Bhamare, Lee Copeland, Lynn McKee, Markus Gaertner, Marlena Compton,  Matt Heusser, Orian Auld, Rick Baucom, Selena Delesie, Shmuel Gershon,  Terri Moore,  Thomas Ponnet, Timothy Coulter, Will Usher and Zach Larson. Thank you all for helping me make those leaps of faith. More to the point, thank you for having the faith in me that I'd be able to actually do what you believed I could do! Thank you for what has honestly been, at least as far as software testing is concerned, my greatest year (and remember, last year was pretty awesome, too. I didn't think I'd be able to top that!).

Here's to an every bit as exciting and fun-filled 2012. I'm looking forward to seeing where I might leap next :).

Exercise 37: Symbol Review: Learn Ruby the Hard Way: Practicum

At this stage, we've been given a bunch of commands, keywords, and options that we can used in our programs. there's a bunch of others we may not yet really know how to use, but it's a good idea to get familiar with them anyway. In this exercise, we're asked to do some sleuthing and see if we can figure out what all the stuff we've been using actually means. Below represents my best efforts to figure these things out.

Zed makes the point that he considers these to be the symbols and keywords that are important to know.


alias - associate a method and make it synonymous with another method.

and - flow control operator with low precedence that means do x and do y. Not to be confused with &&, which is a boolean operator with high precedence.

BEGIN - Designates, via code block, code to be executed unconditionally before sequential execution of the program begins. Sometimes used to simulate forward references to methods (comes from,and I'm only slightly sure of what it means).

begin - Together with end, delimits what is commonly called a “begin” block (to distinguish it from the Proc type of code block).

break - terminates execution of a code block and jumps out of it. Think of a case statement, as that's where I'm most familiar with seeing it being used.

case - consider it like a stack of related if statements. It's a more simple system to

class - defines a object and its methods that can be used in ruby

def - used to define a function

defined? - determins if a method refers to something directly (a string, a  number, etc.)

do - execute everything that follows as though it were part of the same block

else - do this if all other conditional statements are not met

elsif - doo this if the first conditional statement is not met

END - defines a section of code that can be run at the end of a code block

end - end of a block of code

ensure - usually run with a rescue statement, even if the rescue statement doesn't get run, the ensure statement will run

false - a boolean value, it's sued to evalute whether or not a statement will run (used often with while and unless)

for - keyword to define the start of a for loop

if - keyword to define the first conditional statement

in - run the steps in the for loop that match this condition

module - synonymous with function, it's a scope where local variables are not aware of other values

next - an iteration step, modifies the value of a variable even if no ction is performed

nil - no value

not - is not this value

or - do if an example is condition 1 or condition2

redo - re-executes a code block without regard to conditions of varibles or state of the program

rescue - error handling section of code.

retry - associated with rescue, has the program try the section of code where the rescue statement resides again.

return - value sent out from a function to the main routine

self - the area of code being run at any given time

super - looks for anc can call all factors associated with a class or method

then - makes posible a conditional statement on a single line (i.e. without having to use a semicolon)

true - do this if the value referenced is true

undef - dereference a method or class for use in a given scope

unless - the opposite of if

until - perform an operation up to the point a condition becomes true

when - options associated with a case statement

while - run forever as long as a condition is not met

yield - Called from inside a method body, yields control to the code block (if any) supplied as part of the method call. If no code block has been supplied, calling yield raises an exception.

Data Types

For data types, write out what makes up each one. For example, with strings write out how you create a string. For numbers write out a few numbers.

true - logical data type - while true (do something and keep doing it until expression evaluates to false)

false - logical data type - while false (do something and keep doing it until expression evaluates to false)

nil - has no value or a value of nil (is empty) a = nil

constants - data type that starts with a capital letter. If value is changed ruby will warn you that you have changed a constant. Pi = 3.14

strings - a collection of characters a = "hello there"

numbers - any digital value  a = 1, b = 2.4

ranges - a grouping of numbers  (1..10) or (1...10)

arrays - a special container that can contain many vliues under the same variable name value["one, "two", three", "four"]

hashes - similar to an aray, but with a way to associate values Hash["a", 100, "b", 200]  #=> {"a"=>100, "b"=>200}

String Escapes Sequences 

For string escape sequences, use them in strings to make sure they do what you think they do.

\\ - escapes a back slash so that it can be used in a string and not treated as a special character

\' - escapes a single quote so that it can be used in a string and not treated as a special character

\" - escapes a double quote so that it can be used in a string and not treated as a special character

\a - actually creates a bell sound alert in a string

\b - actually shows a backspace when printing a string

\f - representa a form feed (not sure where I would use that, but OK)

\n - prints a literal new line

\r - prints a literal carraige return

\t - prints a tab character

\v - vertical tab (not sure where I would use that, but OK)


Some of these may be unfamiliar to you, but look them up anyway. Find out what they do, and if you still can't figure it out, save it for later.

:: - call a constant value (similar to how a method is called with a '.')

[] - element set (used with arrays)

** - exponent arithmetic operator (2**5 == 32 evaluates to true)

-(unary) - ???

+(unary) - ???

! - logical NOT operator ( as in if a&&b evaluates to true, !(a&&b) is false)

~ - Binary Ones Complement Operator (or "bit flipper" which admittedly I have no idea where or how I would use)

* - multiplication arithmetic operator (4 * 2 == 8 evaluates to true)

/ - division arithmetic operator (4 / 2 == 2 evaluates to true)

% - modulus arithmetic operator (returns a remainder, such as 5 % 2 == 1 evaluates to true)

+ - addition arithmetic operator (as in 1+1 == 2 evaluates to true)

- - subtraction arithmetic operator (as in 3-1 == 2 evaluates to true)

<< - Binary Left Shift Operator

>> - Biary Right Shift Operator

& - binary AND operator

| - binary OR operator

> - greater than comparison operator (3 > 2 evaluates to true)

>= - greater than or equal to comparison operator (3 >= 2 evaluates to true, 2 >= 2 also evaluates to true)

< - less than comparison operator (2 < 3 evaluates to true)

<= - less than or equal to comparison operator (2 <= 3 evaluates to true, 2 <= 2 also evaluates to true)

<=> - combined comparison operator (returns different values, 2 <=> 3 returns 1, 2 <=> 2, returns 0, 3 <=> 2 returns -1)
==  - equals comparison operator, as in 12 == 12 evaluates to true

=== - special equals option when used within a case statement ((1...10) === 5 evaluates to true)

!= - not equal (2 !=3 evaluates to true)

=~ - equal or bit flipped ???

!~ - not flipped???

&& - this is an "and" operator" as in "evaluate this and evaluate that"

|| - this is an or operator, as in "evaluate this or evaluate that"

.. range value including end points. 1..10 includes 1 and 10

... range value excluding end points. 1...10 does not include 1 and 10, but does include 2 through 9.


That's a lot to absorb, and as you can see, there's a few places where I still don't now what these are or how to effectively use them, but that's OK. The point is to get used to seeing them and make an effort to understand them and to use them. The key is that there is a lot of flexibility, and that there's really very little in the language that is rigid and formalized, just a few keywords, operators an data types. Of course, the complexity that can be created with those tools is pretty immense, especially when we put the object capabilities into the mix (which we haven't done too muh of yet).

Wednesday, December 21, 2011

Don't Rely on Your "Future Self"

For those who are familiar with my Personal Blog (mostly inactive now that I spend most of my writing time on TESTHEAD), I have a number of posts related to handling money and avoiding debt. I avoid debt for many reasons, but the biggest reason is that I do not trust the entity that I call my "Future Self".

My Future Self is implicit in any arrangement I make. Of course, I have only the best of intentions with My Future Self (I don't think any of us want to consider we will be slothful or shiftless or unreliable). Still, the truth is, My Future Self is just not as reliable and as pliant as I want him to be, and this gets more obvious the further out I look. Sorry for bringing this up again, but this point was really drilled home to me this summer. I had lots of plans that related to getting in shape so that I could consider making a shot at a "Legend's" division competitive run in the United States of America Snowboarding Association South Lake Tahoe Series once again (it has been several years since I competed, and I had high hopes I'd be able to get back on that horse again). Well, my bone breaks scuttled that plan thoroughly, certainly for this year. Imagine if I had bought a season pass and new gear with the hope I would be competing this winter! I would have made those purchases based on a Future Self that never materialized (and could not materialize).

When I take out debt (financial, technical, or other nature) I am, likewise, putting My Future Self on the hook to take care of it. In all cases, this involves interest (whether it's codified as an interest rate or not, any decision put off until later costs in extra money, extra effort, or extra emotions, bet on it). When I was younger, especially, I was much more willing to spend and pay later. I had the attitude of "So what, it's only money, I can always make more!" Well, yes and no. With small amounts, it's true, but did I really want to tie myself down to potentially a lot of work and effort later on for an experience or a memory that may not even be relevant those months, or years, later?

I have a back log of books that I have to read. Yes, have to, because I made a verbal agreement to review them. Many of them have been provided to me for free, and therefore, I have made a "gentlemen's agreement" to work through them. Thus, I have made sure that My Future Self must put aside the time to read, work, ponder and reason his way through them. If he does not, then he goes back on his word. That is something I do not want to see My Future Self (or My Current Self, frankly) ever have to do. No matter how I look at it, this is time I must spend on a verbal commitment. Of course, I believe this will be beneficial, a good investment both in the way of knowledge and experience, and I will have an additional artifact for others to look at and decide if they will consider it worth their time to read for themselves. Still, it's a process that depends on me carving out time to do it, and often, it feels like that time is harder and harder to come by.

In some ways, I think that "time debt" is the most dangerous of debts, even more so than monetary or technical debt (they are all intertwined, of course). This is, I'm sure, sounding ironic coming from me, someone who prides himself on being "frequently busy" engaged in many endeavors. It's one thing to be doing a lot of stuff. It's quite another to put ourselves into a time debt that we will never be able to effectively manage or eliminate. Additionally, there's no way to bank, stretch or ration time. You can't save up time to use on a rainy day; everyone gets the same 84,600 seconds; 1,400 minutes; and 24 hours as everyone else. Time can only be used, and any time we decide to do one thing, we are deciding not to do something else... and really, get the thought of "multi-tasking" out of your head. I do not believe humans can do it effectively. Even super fast computers don't actually multitask; they split their attention among a large number of processes and cycle through them. It's an illusion, and an expensive one when scaled out to a human life.

Consider this my way, both during this end of 2011 and beginning of 2012, to encourage everyone to "honor thy energy" (with thanks and pre-apologies to Merlin Mann ;) ), and please, do what you can to inconvenience and engage Your Present Self as much as possible, and don't overburden Your Future Self. They have enough working against them as it is without our help!

Exercise 36: Day 4 (Adjusted): Designing and Debugging: Learn Ruby the Hard Way: Practicum

It has been interesting and even a bit fun to play this, but I think it's time to move on.

This last step contains a couple more sections and rooms, and a choice at the end. I'm going to include those pieces here and let the game conclude now. I may well play with this some more later on and experiment with things like regex and other methods (right now, it's critical I get the exact words right. if I don't I die, but I want to move on from here as well.

I like the require statement and find it to be very helpful. It's great to be able to separate out each area and treat it as its own little module. that alone is a big plus and is easy to navigate and follow. I can imagine it must really be a plus with really big projects. You still have to know what's in the modules and what they relate to, though, otherwise it's just code.

Tuesday, December 20, 2011

The Cult of SET?!

I think it was last year around September, when Matt was interviewing Goranka Bjedov and Dan Downing for TWiST #10, and in the closing minutes, when Matt made a joke about playing Blackjack, Dan mentioned "I don't, but I play SET!". I thought, "huh, that sounds interesting" and then let it drift out of my consciousness. However, it wouldn't be too many months later that I'd be with a gathering of other testers, and they'd mention the game of SET as well. SET? Why am I hearing that name again? A few more months later and another tester gathering, and as we're all talking, out come cards with interesting symbols, and a group of testers gathering around them. What is this strange game, I wonder? Sure enough (as if you hadn't already figured out), there it was again. This mysterious game of SET, and a group of testers all actively playing it, often for hours.

At CAST in 2011, after the first conference night's activities, we all came back to the hotel, and sure enough, not ten minutes pass that a group of testers has not busted out the SET cards and played for hours. What was it about this game that seems to be so ingrained into my fellow testers' consciousness? More to the point... why had I not heard of it before?

I think it's safe to say that a lot of test community folklore had gone by me unnoticed for years, because until 2009, I wasn't really in any way directly engaged with the broader testing community. As I came to be more aware of it, I started to understand more of the things that testers do, including various card and dice games to help both pass the time, but more importantly, help testers recognize patterns and issues in places they otherwise might not see them. It's in this context that I think SET fits brilliantly.

OK, I have a feeling I'm not the only one late to the party on this, so I am willing to bet there may be a couple of you out there thinking to themselves "OK, Mr. Testhead, what is SET?!" Put simple, it's a card game where any number of players get together, and the dealer lays out twelve cards in a grid four cards long by three cards deep... like this:

You may notice that the cards have various things in common:

1. There are three colors used (red, green and purple).
2. There are three shapes used (diamonds, ovals, and squiggles).
3. There are three shadings used (empty, lined, and solid).
4. There are three counts for shapes (one, two and three).

Three cards make a set if, in each of a card's features (shape, color, fill, and count) every card matches the others, or no cards match each other. As an example, one of the sets you can make is with the three single diamond cards. They are all the same count (one), they are all the same shape (diamond), they are all a different color (red, green and purple) and they are all a different shading (solid, lined and empty). Any property has to match on all cards, or has to not match on any cards to be a valid set.

So what's the point? The point is that, with these twelve cards, you try to see how many sets you can find before the other players do. The way that we've played it at tester gatherings has been if you find a set, you take those cards out of play and you hold them, and new cards are dealt. The player that finds the most sets when the cards are exhausted wins the game.

There are a variety of different rules that can be used in SET, but they are all variations on the same theme. Find as many SETs as you can. You can also play the game yourself, and there are a number of web sites that feature frequently updated puzzles. In the single version of the game, the most common approach I have seen has been 12 cards are dealt, and in the twelve cards there are six sets. Your job is to find them (and often a timer is kept to see how long it takes you to find them). Based on the above graphic... can you find all six sets?

I think that the draw of this game specifically for testers is the fact that it's a quick game to get up to speed with and understand, but more to the point, it helps to remind us that patterns are all around us, and things that we often think we see, we don't really see unless someone else sees them, or we spend the time and trial and error our way around them. This is a great reminder to us that there are many ways we can sharpen our problem solving skills and also sharpen our own perceptions.  The point was brought home to me because, last week, one of my co-workers, as a "secret snow person" gift, bought me my own SET card deck. Now I can jump in and be a part of any tester gathering, too, and I can also practice on my own and see if I can sharpen my own perception and ability to pattern match.

If you'd like to play online, here's a good version of the game. It resets after you find each series of 6 sets, so you can play as little or as much as you want to :).

Exercise 36: Day 3 (Adjusted): Designing and Debugging: Learn Ruby the Hard Way: Practicum

For those who saw my "mea culpa" post yesterday, "Guilty as Charged", that would actually be "Day 2" of this project. In truth, it would be "Day 11 - 9 Days of Procrastination and Putting it of Until I Couldn't Take it Anymore", but that's nowhere near as catchy a title ;).

As a reminder, here's the original "assignment" that Zed set up for us to help us practice and get into the habit of getting these techniques under our skin.


Write a similar game to the one that I created in the last exercise (Exercise 35). It can be any kind of game you want in the same flavor. Spend a week on it making it as interesting as possible. For extra credit, use arrays, functions, and modules (remember those from Ex. 13?) as much as possible, and find as many new pieces of Ruby as you can to make the game work.

There is one catch though, write up your idea for the game first. Before you start coding you must write up a map for your game. Create the rooms, monsters, and traps that the player must go through on paper before you code.

Once you have your map, try to code it up. If you find problems with the map then adjust it and make the code match.

Again, I admit I failed at this, in the sense that I got all hung up on how I was going to map it all out and find a tool to draw it all up, etc. In short, I got lost in the thick of thin things for this, when I should have been focused on doing a little at a time. Yesterday I committed to getting the first story points into code, and demonstrated a proof of the ideas. For today, to make things a little easier to manage, I've split the individual functions into separate files (well, most of them). The main file has four functions that I'm keeping there for now. Those are the prompt, the die function, the "take a break" function (really just a place that I can direct the user to say "the ghosts are figuring out what to do with you now, and end gracefully), and the start function. So here's what it looks like right now:

And this is an example of the game output as of right now:

Personally, I find this approach to be pretty effective. Having each function that would be longer than a screen in its own file is a good way to go and see what I am doing without having to constantly scroll through a single listing and then jump back. This way, if I want to change one module, it's easy to see what changes I want to make and isolate those changes to that one location. it also helps me see patterns and makes the idea of refactoring easier to focus on. If I notice that I am repeating code in a number of places, I can determine if it would be easier to pop those repetitions out and make s single module that encapsulates those items and make a single function out of them. Case in point. I have a part of my story where, if the user does something, the character dies. Additionally, there are places in the game where the automatic action finds them falling into the basement, which is filled with water, and they drown. Mention it once, that's fine, mention it twice, well, that's an alert. Mention it three times... maybe it's better to pull the process of falling into the basement into a single function. That way, if I decide to change the behavior of what happens in the basement, I can rework one file rather than have to open a bunch of files and rework the falling into the basement process and what it actually means.

For tomorrow, I am now venturing into the house, and its' time for some new "stories". The kitchen will have a puzzle that will include a simple guessing game to continue, and then its time to explore the rest of the house and, dare I say it, more possibilities of falling into the basement, but I should find other ways to have the protagonist meet their grisly fate, too. The basement will become a boring way to die, otherwise :).

Monday, December 19, 2011

Maintenance Mode

As I was standing with our design director and talking about some of the new features planned in the coming weeks and months, I was excited about the prospects, I was intrigued at what that would mean for me in my testing, but at the same time, I had a sinking feeling... I realized that "Oh no, I have a whole bunch of tests that are going to effectively be broken with these changes".

This is a typical situation. I can count on the fact that I will be doing some tweaks and changes on the sites that I work with, and that my scripts are not going to be evergreen. At the same time, it can be frustrating to have to gut whole sections and retool scripts. These are times when I must admit, I've been tempted to just throw up my hands and say "Gaah, what's the point?!"

Here's where I want to ask the other Lone Testers out there... how do you deal with "Maintenance Mode"? I understand when you are working as a tester and you have the advantage of an automator or an automation team, but what do you do when *you* are the automator, and the exploratory tester, and the regression tester, and the fill in the blank tester? I don't have the opportunity to hand off the maintenance work, and when I do the maintenance work, I'm not testing.

I will say that I do find a lot of the rework options and the ability to create "macros" in the selector.rb file to be very helpful in the maintenance steps. I like this option because I can focus on just making the language of the steps be business rules and say "look for the following", while having all of the individual steps grouped together. the biggest problem with that approach, though, is that I often have to "unfactor my refactoring" and plug in the original group of steps to see what's no longer working.  Don't get me wrong, each time I do this, I learn a little bit more, and I learn which refactored steps are actually effective and durable, and which ones I need to reconsider and, well, refactor the refactoring.

I am serious, though, for those who often find they have to make large scale changes to their scripts, how do you effectively balance your work load and focus so that you can do both, or do you just let everyone know "I can do X, or I can do Y, but if you think I can do X and Y at the same time, you're nuts!" Right now, I'm doing the latter. I'm open to suggestions, seriously :).

Guilty As Charged

A Boy Scout camp out. A thrown out back. Grading and reviewing students for Test Design class. Being sick. recovering from being sick. Catching up for work from being sick. A conference call. Multiple holiday parties on successive days. Helping to hang lights for one of the multiple parties on successive days.

What do all of these things have in common? Well, first, they are part of the reason for an unintended but perhaps much needed break from blogging. I say that because, honestly, I realized I've posted over 100 blog posts in ten weeks. That in and of itself is not a huge deal, and it's been helped a lot by the fact that I have been posting daily synopsis of two books for much of those ten weeks, but it left me a bit stretched and somewhat fatigued, and in need of a recharge. The truth of the matter is, it was all an unintended but somewhat convenient way for me to avoid and delay my doing a project for "Learn Ruby the Hard Way". Yep, I fell prey to the very advice that Zed warned about. Which advice is that?

One final word of advice: Every programmer becomes paralyzed by irrational fear starting a new large project. They then use procrastination to avoid confronting this fear and end up not getting their program working or even started. I do this. Everyone does this. The best way to avoid this is to make a list of things you should do, and then do them one at a time.

Looking back, this is exactly where all of these things became convenient excuses for me to not start a big project. There would always be tomorrow. I'd be inspired after I got through this recent challenge that I had to take care of. I'll hit it as son as I feel better. No, as soon as these holiday parties are over. Ten days pass, and nothing. Well, I shouldn't say nothing, really. I have ideas, many unfocused. I have a vague framework in my head, but no firm commitment and, worse, no tangible code towards this challenge. I've been coding for work, and I have some better appreciation how to do things in the Cucumber and Capybara world now, but I'm still in the same old place I always find myself in. I'm good at modifying other people's code, but I'm awful at starting my own.

Also, I'm guilty of breaking my own covenant with myself. I said I would post the good and the bad of this process, and here's where the truth of the silence comes out. It's easy to post if the project is easy, or if the challenge is something I can overcome in a few hours or turns out to be trivial. It's another thing to post and say "well, I have another excuse as to why I didn't do what I said I'd do, and here it is." I didn't want to have to write that, so I kept saying I'd make my "mea culpa" when I completed the project and post it. Even under this "personal delusion", I didn't think I'd be seeing a ten day break between posts.

So I've decided it's time to go back to my original plan. This blog is my accountability partner, and more to the point, to all who read this blog, you are all my accountability partners, too. Therefore, I hereby bring myself back to the original plan, and I'm not going to wait until "tomorrow" to post what I should be doing, I'll continue it here, and here starts today.

My first "problem" was that I got hung up on how I would map out the program I intended to write.  I hate doing flow charts and all of that, so I was delaying getting started on the flow chart. Then I was wondering what I would use for the flow chart. Then I fell into an utter lack of imagination as to how I was going to actually pursue my original plan of walking through a haunted house. From there, it was always a "wow, that's going to take a long time, I better hit this tomorrow"... and tomorrow never came.

I've made points in this blog many times that I do this blog and I talk about these things not because I am good at this stuff, but because I'm exceptionally bad at doing this stuff at times. Still, I maintain that the same tools work in these cases. Having a public face, being publicly accountable, and being willing to say "OK, I messed up on this, but I'm going to get back into the swing here and now and keep going" helps do exactly that.

A Tour Through a Haunted House

My mistake was that I got hung up on trying to make a high level plan from the outset, and that high level plan terrified me. I tried to code a story I couldn't picture in my head, and I tried to flow chart before I ever had a story to work with. So this time, I'm going to start much smaller. I'll start with some simple stories.

There is a large mansion that has been derelict for close to a hundred years. It stands in an over grown forest with little but a dirt road leading to it. the house itself looks like it may fall in on itself at any moment. Stranger still, many people say that the house is haunted. So why would I want to go in it? Because some locals have said that the house contains an ancient artifact made out of gold. That's the rumor, anyway, no one who has gone after it has been able to get past the fact that every time they try to approach the house, something breaks  inside of the house to prevent them from looking very closely. Stairways collapse under the weight. Boards on the floor break. Doors are rusted shut, and occasional flooding has filled the basement with water. Falling into that basement is no fun, as there's little in the way to get out of it. So if I'm going to explore the house, I need to make sure I have a game plan. 

I've heard some people say that the road itself is dangerous, that there's a large sinkhole that I can fall into if I don't turn at the right place (there's a tree that's grown up in the middle of the old road. If I go to the left down the obvious curve, I'll hit the sinkhole, but if I drive over the root bump on the right, I'll be OK. 

That gives me a legitimate starting point. Now I need to map these elements as I've decided. Right now, rather than worry about the entire story, I have a simple first block to work with, the road up to the house:

Diving up to the house (1st step)
Choice: drive around the tree that is in the middle of the road.
If (left turn)
  Land in sink hole. Crash results in killing the driver (me). End of the line.
Else (right turn)
  Continue on up the road to the house.

So that's not a lot to work with just yet, but it's enough to get me started :). From here, I can start exploring other avenues for this project, and now, I can at least say I've started rolling the rock again. From here, there will be a post each day, regardless of if I make any progress or not (see, I didn't actually say I'd do that last time, so now I'm taking away my "out" (LOL!) ). I think that now that I have a loose framework started, I'll be able to make more headway as I go forward.

Tuesday, December 13, 2011

Test Design Pilot Comes to an End

It's been an adventurous six weeks, to say the least.

While Saturday marked the official end of AST's latest Black Box Software Testing class, Test Design, I've been frantically reading, comparing, rereading, and grading exams. As the class has now wound down, and the last details related to announcing completion of the course to the participants, it's time to reflect on what I've been through for the past six weeks (that includes setting up the Moodle environment, populating the quizzes, the forums, and a lot of administrivia type stuff that I have dealt with here and there, but never quite to this scale. It was indeed enlightening.

So what is Test Design? Well, it's the third and final of the original sequence of classes that makes up the core Black Box Software Testing curriculum. If you were to combine all three courses together (Foundations, Bug Advocacy and Test Design) you would have a full university semester course worth of material on Software Testing. That was the point from the outset, and now it's all here, under one roof, and able to be taken by those who sign up and commit to participate. Of course, you can always watch the materials and do the coursework on your own time for free, but some amazing interactions happen within the structured, facilitated course. For that reason alone, I'd suggest coming in and participating.

Test Design is a massive survey course. It deals with a tremendous amount of information at a breakneck speed. "Drinking from a firehouse" is a quaint figurative turn of a phrase, but in this case, I believe it is 100% appropriate. There is just so much information and not a lot of time to digest it all. As Cem states in the lectures in the first couple of minutes, you're not expected to absorb it all, nor are you expected to absorb it all on multiple viewings. Over time, as you practice and consider the techniques, and apply them, you will get better and understand which ones work best where.

If there's one specific gem above any others I would suggest as a reason to get familiar with this material, it would be the Heuristic Testing Strategy Model (HTSM). This is an excellent framework in which to hang testing of any software component, ranging from a single function to an entire system. It's huge, and there's a lot of questions that you can ask of a product, and each question can help guide to to more questions and more exploration. It's not a true "map" to testing, but it's a nice encapsulation of a bunch of different techniques, domains and areas where testing can be applied. Not all pieces will be relevant all the time, but it's amazing how much this one item of the course adds to an overall testing strategy.

The labs for this class range from very basic to significant involvement. Unlike in previous courses, group work is not as emphasized, though the option to pair on most assignments is there. The Exam Cram forum, from which the final exam is drawn, is double the length of Foundations and Bug Advocacy. This means a lot of questions to answer, but also a lot of different parameters to consider, with a lot of tips and techniques to apply immediately to your workplace environments.

Are those dreaded quizzes still there? Well, yes, although interestingly, I think that the quizzes this time, while structured in the longer, less prone to guessing right answers format, I felt the quizzes were more straightforward than in the previous two classes. I think that may be because this was the class I came in with the least preconceived notions of what the answers should be; I hit a lot of "first time material" in this course, at least first time for me, and interestingly, I think that was a help. I didn't have what I felt were "gut answers" that felt right, but were wrong on further reflection. I actually scored beter on these quizzes than I did on Foundations and Bug Advocacy. Your mileage, of course, may vary.

I say a lot of this with a tremendously heavy amount of bias; I help teach these classes of course. Were you to take my recommendations with a hefty grain of salt, I'd totally understand. Having said that, though, I absolutely feel this is a worthwhile class. It's challenging, it will be hard to manage, it will overwhelm you, and I think you'll be really happy that you went through it regardless of all that :). The Pilot is over, but there's still time to get in on the next class. It will be offered again in March, 2012, and Cem and I will be the instructors again (plus others, I'm sure :) ). If you've completed both Foundations and Bug Advocacy, and want to take it to the next level, here's a golden opportunity to participate in a challenge that will make you stretch and grow... in good ways, I promise!