Syndicate content
Updated: 14 hours 16 min ago

Slice AND Dice Your Data

Fri, 02/03/2012 - 06:42
It's been a data-riffic week. It all started with a product comparison, then segued to a series of staffing questions, and is gearing up to conclude with a big bang load test. Suffice to say I've had a whole lot of paper shuffling around. These projects have two things in common: they're all dependent on the collection of large amounts of data; and their success depends on the clear presentation of that data to support my (brilliant, of course) conclusions.

So, how do we get our hands around all that data? And once we have a conclusion, how do we present it effectively?

Slice up the data. Then start over from the raw data and dice it an entirely different way. Repeat.

The point is to look at the data from several angles to gain comprehension. Let's take the product comparison as an angle. It was a pretty straightforward project: We need a CMS. Which one should we use? There are literally hundreds of CMSs in this world, and a whole lot of information available about most of them. Let's commence data analysis:

  • Slice. Make a feature comparison table, showing which ones have the features we're interested in.
  • Dice. Map out the release frequency of modules, showing how quickly these introduce new features (as a proxy for future feature development pace).
  • Slice. Figure out the annual cost of each CMS.
  • Dice. Describe the community around each CMS, including number of job postings/candidates, presence and activity in forums or other documentation, and breakdown of current users in our industry.
Etc. etc. etc. You get the point. The idea is to take the data available and look at it from several different angles. Each angle will point up some CMS that is more appropriate than others. By starting over each time, you avoid bias based on your earlier analysis. Collectively, the slicing and dicing produces a small list of really good candidates, and provides comprehensive grounds for argument.
So often we deal with large amounts of data, and it's easy to get overwhelmed and make a choice based on just a few data points and a rough guess. Take the time to cut through the data in a few ways, though, and your choice will not only be more obvious, it'll also be a better decision.
Categories: Software Testing

Always Plan?

Mon, 01/30/2012 - 10:57
Almost no matter what process you use, there's almost always the idea of planning. RUP has its Inception Phase. SCRUM has its sprint kickoff and grooming. Even Kanban has a backlog and planning in the form of creating item cards. Apparently, we all really think planning matters! We may disagree about timing, how much we plan, etc., but we all like planning.

Planning gives us a lot of things:

  • An explicitly-expressed understanding of what we're doing
  • An explicit communication of how hard that is (points, hours, whatever)
  • Accountability for how well we did (whether you call this velocity, signup, whatever)
  • Insight into trends for macro planning (i.e., we get roughly X done every week, so this feature will be done in approximately Y weeks, give or take)
I'd like to make a counterargument: sometimes we shouldn't plan.
There are a lot of things that can be planned - features, data processing, even performance work. There are a lot of things, though, where planning is just guessing. Bug finding/fixing is a good example of this. "How long is it going to take you to fix all the issues we're going to find in this integration effort?" True answer: "Gosh I really don't know. Depends on what issues we find." Planning answer: "Umm... about 4 hours". With a long term concerted effort, you can figure out very rough estimates based on how many bugs you usually find in similar features and . You'll frequently be off by a bit, but statistically you can make it work out, again, with a lot of effort.
With some things and with some time periods, the effort of planning is not worth the benefit. If you can only plan with reasonable accuracy based on a lot of research and tracking, and if you don't have that, you can't plan with reasonable accuracy. Rather than just guess, consider skipping the planning.
For example, I worked with a company that was doing a big Christmas Day launch (yes, it was Christmas related). It didn't matter how good or bad it was, that was the date. We finished all the features with about two weeks to go. It was shaky, of course. If you did everything right, it worked, but we hadn't tried anything else other than the happy path. We had two weeks for testing and bug fixing and any tweaks. So we needed a planning session! Right? Nope. No way. We didn't know what bugs there were; we didn't know how long they would take to fix. Planning would have been a big guessing system. Better to get started, spend a few days learning just how brittle things were, and THEN we can plan.
Most of the time, we should plan. Most of the time we do plan. Every once in a while, we get to a point where planning doesn't make sense, and it's okay to skip it, at least for a while.
Categories: Software Testing

Why I Haven't Been Hiring Testers

Fri, 01/27/2012 - 08:54

As many of you know, my engineering career started in software testing. I'm in engineering management now, and spend most of my time building and managing teams, writing code (product code and test code), and handling technology strategy for various clients. I feel like that's important to mention up front: I am not anti-test.

But.

Well, here's the thing. I haven't hired a straight up manual tester since 2007. I haven't hired anyone to a test position since 2009. I've hired developers, contracted designers, even hired project managers and contracted documentation experts. But no testers. I know what kind of value a tester can bring to an organization... so why haven't I hired one?

Well, partly because the testers that we did hire mostly stayed. That guy I hired in 2007 is still with the company and still doing testing. The guy I hired in 2009 is still with the company, although he has moved into development. We're still getting the testing function.

There's another part, too. I've basically stopped hiring testers as an early team component.

The testing function is hugely important. We do want to know that what we built works and that it fits our customers needs. So why no testers?

Increasingly, I have other people who are embracing the tasks that used to be reserved for a dedicated tester:
- developers have survived - thrived even - while writing test automation
- product owners have been eager to use the product in a structured way
- customer service reps and implementation managers have been able to provide additional context about application usage and behavior
- improved monitoring points out problems in dev, QA and production, and makes the patterns behind them apparent so debugging is a lot easier

Now, for some applications I'd still hire a tester. I'd make that hire when I needed that kind of specialized knowledge. But that knowledge is becoming less and less specialized as more people start listening to the mantra that "quality is everyone's responsibility". We're seeing more people who test, even as I'm around fewer testers.

Test is not dead. Test is more pervasive and discussed than it has been for most of my career. The dedicated tester, however, is becoming more rare. And I think that's actually good.
Categories: Software Testing

The Guess the Language Game

Thu, 01/26/2012 - 08:10
As I'm surfing the net, or riding the subway, I notice ads that contain code. Usually they're ads for job sites or degree programs. Sitting on the subway is actually pretty dull, so I find myself playing that "what language is that?" game.

For example, this is an ad I saw today:



This one was for a job board (job boards play this game a lot). Other common advertisers are training or college programs; and tech or biotech companies. It's a fun mix of languages and styles. Here are some recent ones:

  • a for-profit college: Java
  • biotech company: C++? (I think?)
  • a large college: Java
  • the same large college: JavaScript
  • a job board: that was totally not a language. We'll be polite and say pseudocode
  • another job board: JavaScript
  • a technology company: Perl
The use of actual recognizable languages is surprisingly high!
It's also interesting to watch how languages change. When I first started noticing these ads four or five years ago, the language was predominantly Java or Perl. These days I see a whole lot of JavaScript. I don't necessarily think that it says anything about languages you need to know, but it sure makes a subway ride more fun!
Categories: Software Testing

The Hard Way Gets Easier

Mon, 01/23/2012 - 09:08
There are two ways software development and deployment can go: the easy way; and the hard way. When it's the easy way, code works, deployments are one-click (or one command), and unicorns dance through rainbows during each build. This way doesn't happen very often outside of tutorials and extremely small projects. No, all too often, it's the hard way.

The hard way is characterized by messiness. Maybe the code is sloppy. Maybe the code is great but the deployment process is manual and error prone. Maybe the code and deployment ideas are great but different environments are all hand built, and none quite the same way. Maybe everything's fine, but getting approval takes forever so releases are slow. Maybe the development process requires things that don't get done, so you're stuck waiting on a code review... for days. Either way, nothing ever goes as smoothly as we'd hope. To some degree, "hard" characterizes most software development shops I've seen.

(Tangential note: I'm a consulting engineering manager. I probably see a higher proportion of software shops doing things the hard way. If it's already easy then my services are generally not needed!)

Building software the hard way isn't fun. It's frustrating for engineering, most of whom know better but don't have a clear path (or don't have time) to get from current to easy. It's frustrating for management, who would like to see new features more quickly and more reliably. I know very few people who actually enjoy doing things the hard way.

So how do we break the cycle? How do we make it less hard? We fix it. But we do so slowly. The first mistake most people make when they realize that developing and delivering software has gotten hard is that they try to fix it. All of it. Right now. That's a recipe for failure. If they can't fix it all at once - and they can't - then they don't fix any of it.

The trick is to make small steps toward a fix. Management isn't going to approve stopping all new work for three to six months and completely rebuilding production just to make it easy. So we do things that management can approve. Remember, it's in management's interests to see this problem solved, too; they want to approve changes that will make things easier. They just have to balance those changes with meeting all the other obligations. Hence: baby steps.

Start with finding something small you can change. It doesn't have to solve the hardest thing. It doesn't have to address the biggest problem. It doesn't have to fix things all the way. Our only two criteria are: (1) we can do it; and (2) it makes things a little bit better. Then do that one small thing.

You can guess what comes next. Yup, do it again!

Doing things the hard way is an uncomfortable reality for many of us. We can make it easier, though. Think small, think doable, and eventually what's hard will get easy.

Categories: Software Testing

The "Hardening" Myth

Wed, 01/18/2012 - 05:32
The purpose of software changes as it ages. When we first write something, we're doing it quick and dirty, trying to validate that the core idea is good. We might call it a prototype, a proof of concept, and early alpha, beta, or even 1.0, but the commonality remains: the software has been written with speed and  getting the core of the offering right. This is true whether the core is an algorithm, business process, market hold, whatever.

Once we get through that first phase, though, it's time to build "real software". This is the time you build the software you can grow on. All those things that got skipped in the first phase - error handling, monitoring, administration - need to get put into the product.

With product life cycles being what they are, that frequently turns into "hardening" the prototype. Basically, engineering is going to go off and add administration, and configuration, and error management, and scaling capabilities. Engineering probably says they want to rewrite at least part of the system, but gets pushed (or walks themselves) into the idea of hardening.

Bad idea alert!

"Hardening" is building something that looks like this:



Looks nice on top. Pretty shaky down below.

"Hardening", you see, is a myth. Way back when the team first built the prototype, they either "built it right" or they didn't. They either set up robust deployment, included monitoring, got their configuration and logs into a good location, or they didn't. If they did, then you're not having the hardening versus rewrite conversation at all. If they didn't, then you need to do a rewrite.

"Hardening" is a compromise that leaves you with baggage, slowing you down over time. The symptoms vary. Maybe you have a production system that you can't shut down because no one knows how it was deployed but it's functioning (for now). Maybe your releases are high risk because you have to change configurations in code. Maybe you don't have monitoring, so you only know about downtimes when your customers call (whoops!). Maybe the system has a lot of errors, and consumers are confused, creating a burden on your support or dev team. Whatever your particular symptoms, you're seeing the effect of trying to take a prototype (or alpha) and make it into software that will serve you at scale.

There's no shame in rewriting software. It's not a bad thing to throw out software once it has accomplished its purpose. If you wrote a prototype and it showed that your core algorithm worked, great! It has done what it needed to do. Time to retire it and write the software that will implement your core algorithm at scale.

So don't "harden".  If you can proceed with what you've got, then great. If you can't, bite the bullet and rewrite. It'll slow you down in the immediate term, but it's the right path to long-term velocity.

Categories: Software Testing

Test Intent or Implementation

Mon, 01/16/2012 - 07:32
Writing unit tests for existing code can be very simple. You pull up the method (or API or class or whatever), look at the implementation, and start writing tests to make sure you hit it all. Read method, write test, read method, write test. Repeat until desired test coverage is achieved.

Yay! We're done!

Well, no, we're not.

We've tested what was implemented, that's true.

But did we test what was meant to happen? Did we test the intent?

This is a much trickier question. If we're testing a method that's entirely internal - a helper method, say - then the intent and the implementation are probably identical. After all, the consumer of the method is the guy who wrote it, and if it doesn't do everything he wants, then he's probably noticed by now! If, however, we're testing something that is consumed externally - an API, say, or a library - then the intent may be quite different from what the programmer understood.

For example, let's say we have an API that provides some information. The programmer may have implemented that as a GET with url parameters for each data point (e.g., http://mycoolapi?id=1&name=bob&text=hi). The implementation may be perfectly correct. But the intent may be quite different. The product manager may have meant for the API to be a POST with a multi-part form upload, since the next data point is going to be a picture that can be uploaded. Implementation - perfect! Intent - oooops.

So when you're testing something, go ahead and look at the implementation. Just don't forget to look at the intent, too!
Categories: Software Testing

The Myth of the Passionate Employee

Fri, 01/13/2012 - 04:51
I've had conversations with two separate people in the past week, and in each the person I was talking to said, "No, I really need an employee. I want someone who's going to be passionate!"

It piqued my interest. When you really sit down and parse those two simple sentences, there are several assumptions and definitions in there that are fascinating.

First there's the notion that an employee - rather than a contractor - is needed to display passion. I'm not sure I buy this, although I can see where they're coming from. After all, if you pay a contractor to build something, they're going to do the job and expect to be paid for it, and that's all. If they're good at what they do, they will do a good job and do what it takes to deliver quality work on time. An employee is theoretically more closely tied to the future of the company and therefore will display more passion about it. Unfortunately, this is a loose correlation at best. There are passionless employees and there are contractors who are highly passionate about each of their clients.

Second there's the definition of "passion." I do not think this word means what  my conversation partners think it means. After all, passion merely means "strong emotion". What they think is means is more along the lines of "cares deeply about the future and vision of the company and will work as hard as it takes to see that vision come true." And that is a very different idea. Both of the people I was talking to are company founders. They live and breathe these companies: they stand beside their sons' soccer games thinking about closing the next client; they send emails - and reply to them - at all hours of the day and night; and they've sacrificed normal jobs for this. They want everyone to want their companies to succeed as much as they do, and to work as hard. That's what they call "passion".

Here's a little hint: It ain't gonna happen.

There are people who work very hard for dreams. They do it because they personally are getting something out of it. Maybe it's a chance to be rich ("I'm gonna be the next Google millionaire because I'm employee number 2!). Maybe it's advancement in their career. Maybe it's fame (the guy who came up with Amazon AWS is a rock star in some circles). Maybe it's just because they're really interested in the work.

There are other people who won't work that hard. Your dreams and blood and sweat and tears are their job. They want to do their job, get compensated fairly for it, and go do something else.

Specifying an employee or a contractor won't guarantee you passion or lack thereof. The financial arrangements of the work - employment or contracting - really don't have anything to do with how hard they work and what they want for it.

Working hard or long is also no guarantee of quality. Ask yourself what you really need. Do you really want someone who will be there all the time responding to your emails and putting in the hours - regardless of how good the output is? Or do you want someone who is going to help you build your product well, even if that someone will only do it in 40 hours a week?

So the next time you say you want a passionate employee to work for you, don't. Step back and think about what you really mean. Do you want someone who will build good things? Or do you want someone who is always around? Me, I'll take building things.

Your choice.
Categories: Software Testing

A Rant On Learned Specialization

Wed, 01/11/2012 - 07:35
I've written a few times about specialization in various forms. It's a large point of consideration on small software teams. On the one hand, having a specialist on hand means that the work can get done generally more quickly and better. On the other hand, having a specialist means that when he's not available that kind of work just plain doesn't happen.

Ultimately, we as engineering teams generally have a few fairly concrete goals:
  • deliver functionality to our customers as fast as possible
  • don't kill ourselves - we make mistakes when we work too fast
  • create solid software so that it can survive the onslaught of usage (yay success!)
  • provide management with predictable production rates - they need to know when things are likely to happen, even if it's just an estimate. Most of the time we call this velocity.
None of that says anything about specialist or generalist, at least on the surface. If we have specialists, some parts of our goal become easier; we are more likely to create solid software, and we'll probably do it a bit faster. If we have generalists, though, we're more likely to be predictable; one person being gone doesn't stop everyone else from finishing things, and we have fewer bottlenecks since anyone can jump in to help.
Specialization is occasionally necessary. If you're doing something truly specialized - a new data storage technique, or high volume (read: millions per second) data processing - then you need a specialist. Or two or three. For most of us, though, we're not doing anything that specialized. We're building web applications, or apps for various devices, or installable software. We have to be good software engineers, but the problems aren't really that esoteric. Even in cases where the product is hugely specialized, there is still a large part of it that's just a solid program to do the more commonly needed parts (administration, logging, UI, etc.).
It's a lot like physicians. Most of the time what you need is a general practitioner who is going to know how to solve lots of different kinds of problems that many people need solved (chicken pox, colds, appendicitis). You really only need a specialist when something truly weird is going on - Wilson's Disease, for example.
Here's the rant part: There is another, more insidious, form of specialization that I like to call "learned specialization". This is where a person or a team who could be a generalist decides to become a specialist. This is what's happening when you hear statements like, "I'm the architect. Therefore I have to do all of the design and you can't start that feature yet because I haven't designed it." Or you hear things like, "Well, Jeff should do that because he knows the frobble module." Or "I'd really rather not tackle that story because I haven't worked in the admin before." The team - or one person on the team - is creating unnecessary specialization. There's no reason that John can't learn the frobble module, even if Jeff already knows it. There's no reason that Jorge can't produce a design for a feature and get the architect to take a look (must assuage that ego!).
The worst part of learned specialization is that it's self-reinforcing. The longer that Jeff works on the frobble module, the better he'll know it and the more other team members will just avoid those tasks because Jeff is slowly getting faster and better at working with it. The more Janet avoids the admin module because she doesn't know it, the larger it will get and the more there will be that she doesn't know. If the architect does all of the design, no other team member is going to learn how to design software effectively.
Be vigilant against learned specialization. Any time you see incipient specialization occurring, take it as a training opportunity and get someone else in there. Ultimately, long term software success is about breaking down silos, creating an environment in which there are multiple points of redundancy, and encouraging an atmosphere of training rather than avoidance and burnout. You'll only get there with generalization.
Categories: Software Testing

Positive Negative Assertions

Mon, 01/09/2012 - 09:23
I've been working with someone learning how to test, and we ran across our first negative test case. The method we were testing looked something like this:

new_car_color = paint_car(color)

You feed it the color you want your car, and it returns the color of the new car. If you feed it nothing, it returns the current color.

We'd been writing positive tests that looked something like this:

def test_paint_new_color
   color_i_want = "red"
   color_i_got = paint_car("red")
   color_i_want.should == color_i_got
end

def test_dont_paint
  color_i_want = "blue"
  color_i_got = paint_car("blue")
  color_i_want.should == color_i_got
  color_i_got = paint_car()
  color_i_want.should == color_i_got
end

So when we got to the first negative test, we talked about it and came up with this: "We want to test what happens when we try to paint a car a color that doesn't exist".

The junior tester then wrote up the following test:

def test_paint_no_color
    color_i_want = "not a color"
    color_i_got = paint_car("not a color")
    color_i_want.should != color_i_got
end

Well, it's a start. But our car could be any color as long as it's a color. Is that really what we want? What if we started red and the method painted the car blue whenever it got a color it didn't understand? We wouldn't have a clue!

Instead, we write the method like this:


def test_paint_no_color   current_color = paint_car()   color_i_got = paint_car("not a color")   color_i_got.should == current_color end
We make a positive assertion and confirm that the color of the car didn't change.

Even when we're doing negative tests, our assertions should be as positive as possible. We should assert that something is rather than asserting that something is not. After all there is a large range of things that fits inside "is not" - and we might not like all of them! There is a much smaller range of things that fits inside "is". So wherever possible, we should do positive assertions, even when we're testing a negative case.
Categories: Software Testing

The Game Fad

Fri, 01/06/2012 - 08:12
There is a fad wandering around the software community these days: games. In particular, logic games like SET are becoming very popular in training exercises, interviews, conferences, etc. The basic idea is that playing these games can teach you to be a better tester, or developer, or product manager. Someone who is good at SET can readily see patterns, can show flexibility (use one card in multiple sets), and can make logical deductions. These are all characteristics of a good software engineer. So does this work? Or is this just the next version of the "how many piano tuners are in the U.S.?" questions that were so popular in the 1990s and early 2000s? In the spirit of fair disclosure, I should mention that SET Enterprises is a client. So in my particular case, understanding SET is actually helpful for my job. For most people, though, games are a proxy for the actual work. They're an analogy come to life. Most of us don't build, test, and maintain games. The trouble with software is that it is highly abstract, and so it's hard to really know that any two people understand things the same way. It's also hard to distinguish familiarity with something from "read an article about it", simply because usage of the same thing varies so much across different environments. For example, someone might say, "yes, we used factories" and be referring to test object creation with Factory Girl, and someone else might make the same statement and mean that they implemented the factory pattern. In addition, software engineering is context heavy, and context is less shared than in some other industries. If a bunch of lawyers or CPAs are talking, they can all know that they went through the same base knowledge - the bar or The CPA exam - and so they can assume some commonalities. There is no software equivalent of Generally Accepted Accounting Principles (GAAP). So in order for us to share ideas, we need to establish a baseline of knowledge and skills. When time is relatively short, say, in an interview, we seek out quicker proxies that highlight the skills we feel are relevant. Some of the best testers you will ever see are useless on their first day; they require in depth product knowledge for their particular skills to shine. We can't do that in an interview or at a one hour talk, so we find analogies that we believe highlight those trengths. We play games. So is a game a useful analogy? If I'm good at SET will I be a great tester? If I play a mean game of chess, does that say anything about my skills as a developer? Yes, but only if the skills are actually relevant to the kind of work I'm doing. The visual pattern matching in SET is great if I'm testing a UI centric application, or something where design aesthetic and precision are important. The logic and sequencing that a good chess player displays are great if the product I'm developing is, say, a finite state machine. However, if I'm testing an API, the visual patterns aren't so useful. If I'm writing a simple login module, then advanced logic skills are less important than other skills. Playing games is a lot of fun. So were those logic questions about why manholes are round. But before you put too much emphasis on them, ask yourself if they're really showing characteristics that are important for your particular situation. Then go play some games, if only for the fun of it.
Categories: Software Testing

Quick: RSpec::Core::Configuration::MustBeConfiguredBeforeExampleGroupsError

Wed, 01/04/2012 - 04:27
I upgraded my RSpec version to 2.7 in an old project today and immediately got this error:
arete:textaurant catherine$ rspec spec/* /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:471:in `assert_no_example_groups_defined': RSpec's mock_framework configuration option must be configured before any example groups are defined, but you have already defined a group. (RSpec::Core::Configuration::MustBeConfiguredBeforeExampleGroupsError) from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:168:in `mock_framework=' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:142:in `mock_with' from /Users/catherine/Documents/turnstar/textaurant/spec/spec_helper.rb:25 from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core.rb:71:in `configure' from /Users/catherine/Documents/turnstar/textaurant/spec/spec_helper.rb:17 from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/activesupport-3.0.10/lib/active_support/dependencies.rb:235:in `load' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/activesupport-3.0.10/lib/active_support/dependencies.rb:235:in `load' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/activesupport-3.0.10/lib/active_support/dependencies.rb:227:in `load_dependency' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/activesupport-3.0.10/lib/active_support/dependencies.rb:235:in `load' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:459:in `load_spec_files' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:459:in `map' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/configuration.rb:459:in `load_spec_files' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/command_line.rb:18:in `run' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/runner.rb:80:in `run_in_process' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/runner.rb:66:in `run' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/gems/rspec-core-2.7.1/lib/rspec/core/runner.rb:10:in `autorun' from /Users/catherine/.rvm/gems/ruby-1.8.7-p352/bin/rspec:19
The solution is twofold:
  1. Convert all old-style rspec includes (require File.dirname(__FILE__) + '/../spec_helper') to new style includes (require 'spec_helper').
  2. Make sure that all your specs have " require 'spec_helper'", even the ones that don't have any specs in them. I had one spec file where all the specs were commented out (I know, I know! I'm fixing it!) and it happened to be loading first, and causing the above error.
Categories: Software Testing

Improve, Then Brag

Tue, 01/03/2012 - 10:48
One of the hallmarks of new (as in New Year), is ambition. This year, after all, will be different! This year we will be better, stronger, more efficient, and just all around great. Plus, we've all just gotten off a relatively slow time, maybe even had a vacation. It's time to get back to normal and to get back to work.

There's a temptation to take the zeal a bit too far. After all, the velocity points you got in December were slowed down by vacations, holidays, time off, etc. So we can increase the amount we think we'll do!

Just be careful that everyone on your team agrees.

It's fine to think you'll be better, stronger, faster; we all want to improve. But wait for some actual evidence of it before you go making claims based on being improved. See your velocity go up before you start bragging about those features that will be ready earlier than planned, or the extra features that will make it in. After all, not all improvements happen as fast as we want.

It's simple:

Improve first. Talk about it second.

Get those two backwards and you'll just depress your team and anger your customers by setting another set of unrealistic goals. So avoid unrealistic goals, don't make promises you aren't sure you can fit, and look for improvements before you assume they're out there.
Categories: Software Testing

Toolchain

Tue, 12/27/2011 - 11:08
I work for startups, mostly on web-based software and services (SaaS). Tools are everywhere, and we need to get a lot done. Fast. Our tools have to work for us, not against us. The right tool makes life a lot easier and gets features out the door faster. The wrong tool slows the whole team down, wastes money, and wrecks morale.
So what do I use?
Before I talk about specific tools, let me lay a bit of groundwork. When I'm working for a client, I frequently use their toolchain. When I'm running engineering, we frequently use the toolchain I describe below. Most of the projects I work on are web or mobile web applications, or software APIs (think SaaS).  We're almost always a distributed team, and we usually use some variation of agile methodologies (SCRUM-like or kanban-like). The important part to take away is that we're generally working on multiple things at once, we try to keep those things small, and we push new features or changes into production when they're ready, without waiting for a defined release cycle.
Feature Tracking: Product: PivotalTracker Cost/Level: $18/month will hold until your dev team passes 5 people, then $50/month Summary: I'm not in love with this one. It works pretty well, but there are a few features I wish it had, like: (1) distinguishing between done and deployed; and (2) a UI that doesn't feel so darn squished. Other candidates worth considering:
  • Jira: Too heavy and too pricey. Annoying to configure, and really encourages excessive time spent on tracking ("ooh! pretty graphics!"). It's useful if you have nervous and overbearing management involved.
  • Lighthouse: Good for very small projects with savvy business types. Good email and source code integration and very simple, but little to no workflow or enforcement of procedures.
  • Trajectory: I've heard good things, but not used it. Somewhat niche.
Bug Tracking: Just use the same thing you're using for feature tracking. Don't overthink it.
Source Code Management Product: GitHub Cost/Level: $12/month will hold until your dev team passes 5 people, then $22/month Summary: It's hosted. It's stable. It's Git, which lets the dev team do amazing things. Other candidates worth considering: Just use GitHub
Hosting I can't make a single recommendation for hosting, since it depends so much on your product and your team. There are a couple of scenarios that might make sense:
  • If your goal is cheap, you're on Rails, and you don't have a sysadmin type on staff, use Heroku.
  • If your goal is reliability and you can do your own administration, use Amazon AWS and put your database on an RDS instance.
Product: Heroku Cost/Level: varies based on usage, but the add-ons add up Summary: This is cheap and it's the easiest scaling I've ever done. It's also well configured, which  makes a big difference. Big downsides: frequent downtimes (especially if you use the shared database), and it will only backup once an hour, so data loss is a possibility. Also, use the kumade gem if you're using heroku. The deployment model of heroku alone is pretty bad; kumade helps.
Product: Amazon AWS + RDS Cost/Level: varies based on usage Summary: This lets you start small and will scale with you. It's also very reliable (and can be made more reliable if you have more money to spend). Interaction with Amazon is a solved problem, so scaling and deployment are simple problems. Big downsides: you have to do your own configuration, which means you need some sysadmin skills to set it up.
Development Environment This one varies based on your product and personal experience. I mostly work on web apps, and my preferences look like this: Ruby on Rails, TextMate (vim is fine, too), cucumber, rspec. As long as there ARE build and testing tools in place, let the dev team pick what they like.
Build and Deployment This is another one based on product and personal preferences. Just make sure there IS one. Oh, and the deployment should be something that's run automatically from the build system. The answer here is a tool, not a manual process.
That's my stack. If I've forgotten an element, let me know and I'll be happy to talk about it. If you disagree or recommend a different tool, let me know. I'm always curious to see if there are better tools for my toolkit!
Categories: Software Testing

Always And Never Usually Aren't Either

Tue, 12/27/2011 - 04:39
One of the quirks of coming to software development through test and through business is the healthy fear it provides of absolutes. Things that should "never" be true or are "always" bad turn out to be true on rare occasions or sometimes beneficial. This holds in the software we write. For example, you should never  use the singleton pattern because it adds a hidden global dependency.... But a logger should can be a singleton because you really want to unify logging into one place that's configured by multiple things. This also holds for practices and procedures. For example, we should never use a test script.... But perhaps there is a situation where that would be useful, like in an automated smoke test where the script is in the form of code. There are no best practices at all ever... But I have yet to find anyone who thinks that keeping code in source control is a bad idea (maybe its a best practice!). Regardless of the topic within software, any time you hear an absolute - always or never - be suspicious. When someone talks in absolutes, there's usually a reason they're speaking with such exaggeration. Sometimes they're simply naive. Sometimes they're insecure and trying to hide it. Sometimes they're just seeking attention through dogmatic pronouncements. No matter the cause, be smarter than that. Notice the absolute statements, recognize that they say more about the speaker than about the statement, and move on. Things that seem absolute probably aren't.
Categories: Software Testing

Describe the Unusual

Thu, 12/22/2011 - 06:42
Documentation is a part of my job, like many engineers. I write documentation for end users, training material, documentation for other developers (API docs, anyone?), bug reports... all sorts of things. And like many documentation creators, I can talk for a long time about some of these things.

Saying too much is a very good way to frustrate your audience. They don't want to know everything; they can't absorb it all and they lose the important parts. So follow the cardinal rule of documentation:

Describe the unusual.

Let's assume for the moment that documentation is about describing interaction. It attempts to explain to the reader how to successfully work with the system - whether that interaction is through an API, a GUI, or whatever - and how to understand what the system is doing (i.e., error states, message meanings, etc).

Describing interactions is a huge thing, which is why it's so easy to write a whole lot of documentation. But that's the wrong thing to do. The truth is, most of the time you can assume some basic knowledge, and just describe what's different.

For example, I'm working right now on a logging module for a system. The system right now does ad hoc logging; each component logs in its own way. My logging module will provide centralized logging so we get consistency in log level, storage location, format, etc. When I'm documenting this, what can I assume, and what should I write about?

My audience is other developers who work for this company. They pretty much understand the system, the language, and general development concepts. Great!

So I describe the things that are unusual:

  • instantiating this (custom) logger I wrote
  • requirements around uniqueness and sharing of loggers (class instances)
  • whether it is thread safe (yes) and process safe (no)
  • deployment requirements and the configuration format, for the IT guy
  • log size and rotation rules, which I got from the IT guy
I don't describe the things that developers generally expect from logging:
  • the existence of log rotation and aging
  • when to log at various levels (DEBUG vs INFO, etc)
  • the format of the log entry
I can skip what people already know, which makes the documentation much shorter and makes the important parts more readily apparent. It's easier for the consumers to read and much more likely to be actually useful.
So when you have to document something, whether it's a multi-day tutorial or a simple comment describing how to use a method, focus on the things that make it unique. Describe the unusual.
Categories: Software Testing

Breathing Room

Tue, 12/20/2011 - 11:00
One of the fun parts about the end of the year is how many big initiatives tend to pile up. The culmination of a big project - whether that's a new website, a major refactoring, a release, or something else -  often results in a release. In many ways this makes sense. It is, after all, the end of the year, which is arbitrary but a really common breakpoint and time to assess accomplishments. It's also a relatively quiet time, with many people on vacations, so usage tends to be relatively light (except if you're retail!).

But.

(Ha! I always say "but".)

There's a catch. Big projects are fine, and putting them out at the end of the year makes sense in many settings. The risk is in trying to put out too many too quickly. Any big project comes with risk. When you do many of them at once, you compound your risk, and make it harder to figure out what broke when you're troubleshooting.

If at all possible, give your big projects some breathing room. Push them out and then go work on something small for a brief period. It doesn't have to be long - a few hours or so - but it'll make life a lot easier. Use the breathing period to:

  • get a new baseline of system behavior and identify behaviors and patterns caused by your large change
  • reflect on what you've done and tie up any loose ends
  • review the next big change in light of the new system behavior, configuration, etc.; does anything need to change?
Breathing room is good for humans and good for systems. Take it, if you can.
Categories: Software Testing

Dependency and Redundancy

Thu, 12/15/2011 - 05:50
My software is, of course, perfect. (HA! but go with it). The trouble is that the software I write uses other software; I have external dependencies. For example, Textaurant uses Heroku for hosting, Twilio for text messaging, New Relic for monitoring, and Airbrake for error aggregation.


There are a several good reasons to have external dependencies like these, including:
  • Development speed. Using providers for pieces of the solution lets us focus on the core value we provide rather than the common.
  • Better reliability. People who specialize in monitoring, for example (like New Relic), are going to be a lot better at monitoring than someone who doesn't think about this all the time.
But.... there is a big downside.
When your external provider goes away, you're in big trouble. If Heroku goes down, my app is unavailable. If Twilio goes away, I won't be sending any text messages. It doesn't matter that the outage is on the service provider end - to my customers, it's just the application they use not doing what it's supposed to. And that's my problem.
So we have dependencies, which are really useful and also introduce risk. What can we do about it?
Lots.
Let's take a simple example. My hosting provider had an outage on December 3rd that took down our application. What could have prevented us from being unavailable, even as Heroku was having a No Good Very Bad Day? We could:
  1. Add a second hosting provider, writing into a shared database (or db cluster). Properly load balanced, the hosting provider who was not affected could simply have taken over all hosting duties.
  2. Fail over to a secondary hosting provider as soon as we realize we're down, again using a shared database or database cluster.
  3. Use local data storage in the browser to allow users to keep working. It wouldn't provide full functionality, but it would have given us 85%+ of our features, which is a lot better than simply being down.
There are two common themes running through these options: redundancy and cost. We can increase redundancy.... as long as we're willing to pay for it. How far you go toward ensuring redundancy is tempered by how much time and money you're willing to spend. In the end, it's up to you and to your particular needs. Just consider your dependencies... before they go down and make you consider them in a panic!
Categories: Software Testing

Selective Vacation

Tue, 12/13/2011 - 10:06
It's never a good time to take time off. I'm pretty terrible at vacations in general. And yet, faithful readers will notice that I haven't written here in a week, which is a long time for me - that's practically a vacation!

One of the consequences of being a consultant and having several clients it that someone's almost always on a deadline. If client A just got through a big push (and is now taking a collective few days to decompress), that's frequently when client B is just facing down a big deadline. It makes scheduling vacations... tricky.

So I take selective vacations.

A selective vacation is a vacation... from part of my life. This past week it was a vacation from my blog. Sometimes it's a vacation from a client, or not starting a contract immediately. Sometimes it's a vacation from writing articles. Sometimes it's a vacation from cooking dinner! And sometimes it's a vacation from being home - I spent last week in California visiting family and working.

There are a lot of benefits to a vacation: a change in routine can spark new ideas; getting away can stave off any potential burnout; health benefits accrue from lowering stress on vacation; fun vacation photos or stories spark conversations with your coworkers. At least for me, vacations also provide an appreciation of routine (I do like my routine!). I get a lot of these benefits from a selective vacation - it sparks creativity, and gets me out of a routine temporarily. I also find it very relaxing - not only do I not have all the normal pressures and deadlines, but I'm doing enough work that I don't get stressed over missing important client calls or deadlines.

The point is that if you're like me and find it hard to stop everything and take a vacation, then don't. Take a selective vacation. It offers a lot of the same benefits of a real vacation, but it's a lot more doable.
Categories: Software Testing

Your Software's Personality

Tue, 12/06/2011 - 09:59
Software is a very cold and abstract thing, really. It's nothing we can touch or interact with. So we tend to anthropomorphize it. We think some software is cute, and other software is a workhorse, and still other software tries hard.

For example, Twitter is cute. It has fun little error messages. It features pastels, lots of colors, a good amount of white space, and cheerful graphics.

At the other end of the spectrum, Photoshop is a workhorse program. It has eight bazillion buttons and menus (I know, I counted), and it feels really powerful if you can just get it to do what you want. Of course, getting a program that big to do what you want is something like knowing how to use a workhorse - it takes practice!

As software engineers, designers, product managers, etc., we can help shape our software's personality. We can encourage users to think our software is fun, or simple, or dense and informative - all by the decisions we make while implementing it.

The first step is to decide what kind of personality we want. Are we building a consumer game that should be fun and irreverent? Are we building statistical analysis software where we want it to be prescient and nonintrusive? Are we building software for highly trained users, where we want it to be very consistent and provide hints without getting in the user's way?

Once we understand what our personality is, then we can find ways to express that personality through software. Consider:

  • The tone of the text
  • Graphics and colors
  • Layout - how dense?
  • The presence (and intrusiveness) of help and guidance
  • the workflows - wizards or menus? how short or long?
Your users will give your software a personality - it's up to you to make it the personality you want.
Categories: Software Testing