Archive

Coding for Test

I’m quite excited to announce the release of my latest creation, SiteLab.co!  SiteLab helps small ecommerce websites load quickly and available at all hours of the day.

It does this by analyzing a website for speed issues and continuously loads the website to make sure it’s available for the general public.

Lastly, I added a feature that allows you to make screenshots of your website in any modern browser/OS combination imaginable — yes, iPhone, iPad and Android devices included!

You can check out the application at http://sitelab.co!

Cheers!

Jim Kellas


I joined the software QA ranks at PayPal in 2000.  It was near the end of the big bubble and there was still a major glut of tech jobs vs. people to fill the jobs so some VERY unqualified people were hired to fill the roles, myself included.  The role was pretty simple at the time and didn’t require a lot of technical knowledge.  Luckily, I had a really good – albeit narcissistic – manager to mentor my way into the world of blackbox QA.

Well, things have changed over the past 11+ years.  It’s rare to find QA positions that don’t require some level of programming ability.  Software QA Engineers today (often called Test Engineers) work side-by-side with developers and help build test-able products.  In other words, before a product is built, unit tests and test stubs are created that allow QA to thoroughly test it early and often.  Of course, the test engineer needs to understand the product from top to bottom to request (or build himself) the unit tests and necessary stubs.  This puts QA smack dab in the middle of the initial meetings when designing a new product.  Looking back to my blackbox days, I was always told about a new product after it had been built and expected to test it.  SERIOUSLY?!?

QA engineers today test features from every angle: web server, DB schema, CDN, S3, file system, DRM, cloud servers, co-location implications, server hardening, OS and browser compatibility, A/B tests, load, stress and performance tests, acceptance, fail over, usability, integration, etc.  We’re also responsible to not just report a bug but to dig into the code and find out what happened (or at least narrow down the search).  We need to know why a failure occurred so that we can better prioritize the bug.

QA Engineers need to understand that a bug becomes more and more expensive the longer it exists within the code base.  A bug that makes it to production costs at least 10x more money to fix than if it had been found early which is why we need to identify potential weaknesses early in the cycle.  Never has the term “time is money” ever ring so true.

I often wonder where I’d be if I hadn’t taken a few programming courses in 2004 (C++, Python, PHP).  “Would you like fries with that?” comes to mind.

A while back, I created a useful script to help search for niche keywords on Google.com.  I got the idea from AIR app that I found on the web but it kept crashing.  It also had a bunch of needless features that only helped to slow down the process.

Let me explain what the script is doing so that you can understand how it helps to find niche keywords for you.  I’m sure you noticed that when you start typing in text  on the google.com website, it starts to give you a list of keywords that most relate to what you’ve already typed.  The goal is to show you what other users search for often in order for you to find the most relevant data.

My script takes advantage of this functionality.  By seeding the search with a word or two that relates to your niche market, the niche keyword tool adds 2 alpha-numeric characters after it and captures the keywords that Google returns.  For example, if you seed the script with the keyword ‘how to’, my script will append ’00′ to the end of it and post ‘how to 00′ to Google and save anything that is returned.  The script will continue this process until it’s exhausted all of the letter and number combinations (it’ll end with ‘how to zz’ in this example).

Before writing the keywords to a txt file, it’ll remove all duplicates and list them in alphabetical order.  You’ll need to run the script multiple times with different keywords and pair them with Google’s Keyword Tool to find high-traffic, low-competition, low-cost keywords.  Look for another post about how to get this information.

You’ll need to first install the Requests library from http://pypi.python.org/pypi/requests or you can modify the __getKeywords() method to use the archaic urllib and urllib2 libraries but they are seriously a pain in the ass to use!

Script usage example: python google_keyword_tool.py ‘my keyword’

and finally, the script:

import requests
import sys, os
from string import digits, ascii_lowercase

class KeywordFinder(object):

def __init__(self, keyword):
self.keyword = keyword
self.elements = {'hl':'en', 'q':self.keyword}
self.url = 'http://google.com/complete/search'
self.alphanum = digits + ascii_lowercase

def __getKeywords(self):
"""
gets the top 10 keywords for a given term
"""
headers = {}
headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
headers['User-agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 FirePHP/0.5'
response = requests.get(url=self.url,
headers=headers,
data=self.elements).read()
return self.__parseReturn(response)

def __parseReturn(self, response):
"""
parses out the cruft from the response and returns a list
"""
try:
response = response.split('window.google.ac.h')[1]
return eval(response)[1]
except:
print 'looks like Google is blocking your ip...  <sigh>'
sys.exit()

def __status(self, char1, char2):
sys.stdout.write("Checking: %s %s%s\r" % (self.keyword, char1, char2))
sys.stdout.flush()

def __createFile(self, keyword_list):
filename = '%s/keywords-%s.txt' % (os.getcwd(), self.keyword.replace(' ','_'))
f = open(filename, 'w')
for k in keyword_list:
f.write('%s\n' % k)
f.close()
return filename

def recurseKeyword(self):
"""
recurse alpha-numeric characters following the keyword
"""
keyword_list = []
kws = self.__getKeywords()
for k in kws:
keyword_list.append(k[0])
for char1 in self.alphanum:
for char2 in self.alphanum:
self.__status(char1, char2)
self.elements['q'] = '%s %s%s' % (self.keyword, char1, char2)
kws = self.__getKeywords()
for k in kws:
keyword_list.append(k[0])
new_keyword_list = sorted(set(keyword_list))
filename = self.__createFile(new_keyword_list)
print 'Created %s' % (filename)
return new_keyword_list

if __name__ == "__main__":
if not len(sys.argv) == 2:
sys.exit()
keyword = sys.argv[1]
kf = KeywordFinder(keyword)
keyword_list = kf.recurseKeyword()

Enjoy!

Follow

Get every new post delivered to your Inbox.