Javascript Landscape for Testers

Introduction – Javascript

There’s a lot to know in order to understand what’s going on with the javascript landscape for Quality Engineering testers, especially for those involved in writing browser automation.  One of the biggest complaints recently is literally not knowing where to start, what the dozens of acronyms and terms mean and also what to study and in what logical order to study it.

There is also getting your head around the current use of Object Oriented javascript.  When I first used javascript it was all about making simple web page effects.  Now it is a very popular web language with Object Oriented functionality, used for building full fledged internet applications and used server side with technologies like Node.

Understanding a brief history of javascript is helpful to understanding how to use javascript today and what it means to write javascript tests:

What Object Oriented means in todays javascript is explained well in the following book.  I’ve read many javascript books and as someone with existing knowledge in both Scripting and Object Oriented languages, this is definitely the book that’s been most helpful to me:

Another interesting aspect of Javascript Testing is that that are elements for all 4 of the Agile Testing Quadrants – Unit, Integrated, Performance and Exploratory.

Part I – User acceptance / Integrated testing with Selenium

For BDD there is:

  • Cucumber –
    Using the Given, When, Then Gherkin format

For user acceptance testing there is web page testing with Selenium using javascript, e.g.

For TDD/BDD in Ruby there is:

  • rspec with capybara
  • watir (pronounced “water”)

There is also javascript based Selenium testing for javascript frameworks such as AngularJS:

There is also ‘headless’ browser testing which attempts to address the speed issue of any browser based testing by not actual bringing up a browser window.  Its success will depend on the specifics for a given web site / application.

Part II – Javascript Unit Testing

Then there is the testing of actual javascript itself.  This is primarily about unit testing javascript code.  Here we have two broad areas, one is Node based and one is not.  Node is about server side javascript.  You have a ‘node’ server running that responds to requests.  You can build and use frameworks such as Angular and React and you can also use server side javascript that is compiled into regular javascript which is then sent to browser clients.

As you advance in javascript testing you’ll also want to get a good understanding about spies, mocks and stubs:

As you advance further you may find it useful to understand and use chai – an assertation library for all those ‘should’, ‘expect’ and ‘assert’ statements!


Part III – Performance and Load Testing

Apache Bench
is a (node based) option here.

ab is a tool for benchmarking your Apache Hypertext Transfer Protocol (HTTP) server. It is designed to give you an impression of how your current Apache installation performs. This especially shows you how many requests per second your Apache installation is capable of serving.”


Part IV – Exploratory Testing

You can explore, debug and test javascript by using the browser Console tab to interact with the browser and issue commands

Screenshot from 2017-06-01 07-58-25

You can also use Node at the terminal command line by simply typing node or nodejs

Screenshot from 2017-06-01 07-59-32


A new way to think about tests

Tests that pass are good. right?

That is such a given that it may seem strange to even question it! So here goes:

Tests only add value when they fail

There it is. Failing tests. A good thing. ok I’ve said it.
I’m already removing the arrows, ow! so let me explain:

The idea here is that tests that never ever fail indicate a problem. Tests are supposed to break – when you break the application. After all, that’s why they are there – as safety rails so you can develop in comfort, changing the application as needed and letting you know when your changes break existing functionality.
So what happens when they do break? Well here’s where the quality of the test itself also comes into play. It’s not too hard to write tests that, when they do break (yeah!) they give meaningful information.

Unfortunately it’s also fairly easy to come up with tests that break and tell you something like this:

“Expected true to be true but was false instead”

Sound good? Can you fix that now? Of course not.
So write a test whose failure looks like this:

“Expected the child to be a member of the customers family but they are not listed in the family plan” – now that’s something you can work with !

This is also support for the concept of making sure your tests fails first, i.e. Red, Green, Refactor.  Making sure it fails first provides an opportunity to hone and refine the failure message.

The main caveat to this idea is that tests, if well written, act as documentation  So even if they never fail they can still fulfill that function.  Indeed I have learned about more than one system just from reading the test suite!

A downside to such ‘wordy’ tests is that we can have test code descriptions that don’t match, or get out of sync, with the code being called. This is why we avoid program comments whenever possible, in favor of meaningfully named code objects and function descriptions. However I believe the upside of good and meaningful tests outweighs this downside for these tests.

How to be a TV Trump supporter

Guide to being a trump supporter on TV

– Don’t EVER actually answer the question. Your ONLY goal is to get airtime and then express and expand on the presidents views
– When pressed on questions, find an unrelated incident in the questioners past to talk about
– When pressed more, personally insult the questioner. Find a physical characteristic you can belittle
– When pressed more, find a general thing you disagree about politically and start talking about that
– When pressed more, switch roles and start asking questions instead of answering them
– When pressed with more with facts reply with different facts about somewhat similar topics.
– Wait for the ads to come
– Repeat

Perfected By Kellyann Conway and Jeffrey Lord and Scottie Nell Hughes

Such a shame they have no morals, but hey, find this and I’ll be next on their list !


World of Testing Forums

Mega Meta List of Automated Software Testing Information:

My Favorites
Google’s blog – mind blowing information about flaky tests
“our robot army has been working hard at fuzzing, processing 10 trillion test inputs a day”
“Google has around 4.2 million tests that run on our continuous integration system. Of these, around 63 thousand have a flaky run over the course of a week. While this represents less than 2% of our tests, it still causes significant drag on our engineers.”
Avoid “Tests that use the UI to test business logic that’s exposed through an API (use an API-level test instead!) or implemented in code (how about those unit tests?). Not testing at the right level supports shallow feedback and increased execution time. Goodbye fast feedback.”
“There are no magic, unicorn-filled companies employing all-knowing developers who are creating perfect software.”
“How often have you walked onto a project and everyone on the team got excited and jumped up and down saying how happy they are to have you there?” (i.e. few)
“One thing I consistently ask teams to do during feature design is to include how they plan to measure the value of the feature to customers or business value. Often, only a proxy metric is available, but those work way better than nothing at all.”

Daily vim


/   Search forwards in file
?   Search backwards in file
f   Next on the line
n   Next in the search
N   Previous in the search
set ic       Set search to be case sensitive (default)
set noic   Set search to be case insensitive


/^foo   Search for text ‘foo’ at start of line
/bar$   Search for text ‘bar’ at end of line
/\<foo\>   Search for the word foo
/[a-c]blob   Search for the text ablob, bblob or cblob

Daily Vim

cc – change whole line
c$ change to end of line
:%s/this/that/gc  –  Change ‘this’ to ‘that’ globally in the file and on the line & confirm each
:1,100 s/this/that  –  Change this to that for lines 1 through 100
:e!  –  Reset all edits made in current file
vi + [file]  –  Edit and go to end of file
vi +/string [file]  –  Edit and go to string

Top Ten Terminal Tips

  1. One Letter aliases x=’exit’; alias l=’ls -alFtrG’; alias p=’pwd’; g=’git status’
  2. user – pwd – git branch in the bash prompt, e.g. durrantm@Castle2012:~/Dropnot/webs/rails_apps/linker (master) with
    parse_git_branch () {
    git branch 2> /dev/null | sed -e ‘/^[^*]/d’ -e ‘s/* \(.*\)/ (\1)/’
    PS1=’\[33[01;32m\]\u@\h\[33[00m\]:\[33[01;34m\]\w\[33[01;33m\]$(parse_git_branch)\[33[00m\]\n\$ ‘
    (Add above to your .bashrc file)
  3. automatic CDing shopt -s autocd
  4. git branch completion script (
  5. use tmux
  6. alias hg = ‘history | grep ‘l
  7. .vimrc file for better editing preferences
  8.  mousing in tmux panes with a .tmux.conf file with  set -g mouse-select-pane on &  set -g mouse-resize-pane on
  9. Use locate over find when possible
  10. alias for current code, e.g. alias q=’cd ~/Dropbox/95_2014/work/code/ruby__rails/ruby/ruby_quiz’

Daily Vim

cc  –  change whole line
c$  –  change to end of line
:%s/this/that/cg  –  globally change and confirm each one
:n,m s/this/that  –  change within this range of lines
vi +/this_string  –  open and go to string
vi +  –  open and go to end of line
:e!  –  sreset all changes

Best Bugs Yet

This week ended up representing the cumulation of a years worth of experience at my current employer and it happened through some very special bugs that had been haunting us for months.

1. Ajax Timing

First of all, our UI automated tests have been failing due to ajax and javascript timing issues.  Intermittently and actually quite rarely, say 1-5%.  That’s a problem though because, including branches, we frequently do several hundred CI runs a day, so that means sometimes dozens of runs fail.  This leads to the dreaded lack of trust in test runs which has very negative consequences as ultimately you no longer can trust them to reflect if the product is actually working.

The mystery was why.  The page loads up in 2-3 seconds on our macs and we had a 15 second max wait time which seemed ample.

The clue finally came when I ran the UI tests locally at home on my Ubuntu machine, which ironically is the same OS as the CI machines and also with lower power than my mac.  I ran the specs and they brought up the browser locally, but instead of 2-3 seconds for the page and all the js to load it took 30-40 seconds!

Finally I had the cause of our issues and was able to adjust the 15 in this piece of code for implicit waits to 60 to allow the page to fully load.  Boom.  5 months of a mysterious ajax loading issue finally nailed!

                                         -->  <-- 15 changed to 60
def wait_for(condition_name, max_wait_time: 15, polling_interval: 0.01)
  wait_until = + max_wait_time.seconds
  while true
    return if yield
    if > wait_until
      raise "Condition not met: #{condition_name}"

2. Slow Automated Mobile Tests

Finally tests are passing for mobile devices through the browserstack automated service.  But they are soooo slow.
One of the most simple’fixes’ for this was to simply reduce the tests being run to reflect those workflows actually used on mobile devices.  Two of our workflows are only on desktop.  This reduced the mobile test specs from 24 to 9 and the run time from 42 mins to 18 mins

3.  Passing, Failing, Passing and stopping randomly

The mobile tests have been behaving very erratically in other ways.  At various different points it seems like the device suddenly stops working or responding.  Then we would get 3 test suites in a row passing.  With that good sign we ran a bunch more.  But most failed.  Except the last one.  After a long day of runs, pattern finally spotted.  The different test runs on circleCI (we can have 3 running simultaneously) have 4 slots (machines) with each run).  They create **and destroy** a tunnel to virtual devices at Browserstack, so different runs are killing each others connections.  Not obvious until running multiple (or the same) branch at the same time as other CI runs.  Proved by running one run at a time.  Fix is to start/stop the tunnel once.

command line playtime, grep, xargs, cat and head

Search for this in any of files with filename *.rb

  grep 'this' *.rb

Search for this in files and cat them

  grep -l 'this' b*.rb | xargs cat

Search for this in files and then show their contents with filename on the first line:

  grep -l 'this' b*.rb | xargs head -999

Search for this AND that:

  grep -l 'this' b*.rb | xargs grep --color 'that'

Search for (this OR that) AND other:

  grep -E '(this | that).*other' b*.rb

Rspec Style

My current style for writing feature specs

require 'rails_helper'
RSpec.feature 'Consumer completes 3 step minimal flow' do
  include ThreeStepMinimalFoundationSetupHelper
  include LandingPageHelper, AutoPoliciesHelper, ExitPageHelper
  let!(:zip) { generate_zipcode }
  let!(:vehicle) { FactoryGirl.create(:polk_vehicle, :with_year_make_and_model) }
  let!(:insurer) { FactoryGirl.create(:insurer) }
  let(:auto) { }
  let(:s2_path) { '/auto_policies/three_step_minimal_foundation/s2_primarydriver' }
  let(:s3_path) { '/auto_policies/three_step_minimal_foundation/s3_coverage' }
  let(:p) { }
  before :each do
    setup_landing_page('myquote_non_sem', config_set, mobile: false)
    setup_exit_page('myquote_non_sem', config_set, layout: 'empty_page_with_theme', mobile: false)

  context '3_step_minimal_foundation UI test', :js do
    before :each do
      visit_ready landings_path
    scenario 'landing page with a required field NOT entered', :sad do
      fill_in :landing_zip_code, with: ''
      click_button p.eqv_continue_button
      expect(current_path).to eq landings_path

    context 'landing page with all required fields entered' do
      before :each do
        fill_out_form zip.zip_code
        with_readiness_wait do
          click_button p.eqv_continue_button
      scenario 'now we are on stage#1, the auto_policies path', :happy do
        expect(current_path).to eq auto_policies_path
      scenario 'happy thru all the stages', :happy do
        fill_out_auto auto
        select vehicle.submodel, from: p.css_vehicle1_auto_submodel
        select p.eqv_label_ownership, from: p.css_vehicle1_ownership
        select p.eqv_label_primary_use, from: p.css_vehicle1_primary_use
        select p.eqv_label_miles_per_year, from: p.css_vehicle1_miles_per_year
        select p.eqv_label_parking, from: p.css_vehicle1_parking
        with_readiness_wait do
        fill_out_driver p
        fill_in p.css_driver1_age_licensed, with: p.eqv_age_licensed
       select p.eqv_credit_rating, from: p.css_credit_rating
        select p.eqv_education, from: p.css_driver1_education
        with_readiness_wait do
        select p.eqv_coverage_type, from: p.css_vehicle1_coverage_type
        fill_in p.css_street_address, with: p.eqv_street_address
        select p.eqv_residence, from: p.css_residence
        fill_in p.css_phone, with: p.eqv_phone
        fill_in p.css_email, with: p.eqv_email
        with_readiness_wait do
        expect(page).to have_css p.css_quotes

  context 'sad stages', :js do
    before :each do
      visit_ready landings_path
      fill_out_form zip.zip_code
      with_readiness_wait do
        click_button p.eqv_continue_button

    scenario 'submit of stage1 with vehicle year not selected redisplays with errors and retains changed field values', :sad do
      select p.eqv_option_auto_year_blank, from: p.css_vehicle1_auto_year
      select ownership_option, from: p.css_vehicle1_ownership
      select primary_use_option, from: p.css_vehicle1_primary_use
      select miles_per_year_option, from: p.css_vehicle1_miles_per_year
      select parking_option, from: p.css_vehicle1_parking
      with_readiness_wait do
      expect(page).to have_css p.css_select_vehicle1_auto_year
      expect(page).to have_select p.css_vehicle1_ownership, selected: ownership_option
      expect(page).to have_select p.css_vehicle1_primary_use, selected: primary_use_option
      expect(page).to have_select p.css_vehicle1_miles_per_year, selected: miles_per_year_option
      expect(page).to have_select p.css_vehicle1_parking, selected: parking_option
      expect(page).to have_error_fields

    scenario 'submit of stage2 with driver last name blank redisplays form with error and retains changed field values', :sad do
      visit_ready auto_policies_path(current_step: s2_path)
      fill_in p.css_driver1_last_name, with: ''
      select gender_option, from: p.css_driver1_gender
      select marital_status_option, from: p.css_driver1_marital_status
      with_readiness_wait do
      expect(page).to have_css p.css_input_driver_last_name
      expect(page).to have_select p.css_driver1_gender, selected: gender_option
      expect(page).to have_select p.css_driver1_marital_status, selected: marital_status_option
      expect(page).to have_error_fields

    scenario 'submit of stage3 with street address blank redisplays form with error and retains changed field values', :sad do
      def choose locator
        page.choose locator
      visit_ready auto_policies_path(current_step: s3_path)
      fill_in p.css_street_address, with: ''
      select years_at_residence_option, from: p.css_years_at_residence
      select residence_option, from: p.css_residence
      choose p.css_vehicle1_parked_at_mailing_address_false
      choose p.css_homeowner_insurance_true
      choose p.css_add_violation_true
      choose p.css_add_insurance_claim_true
      choose p.css_add_driver_true
      choose p.css_add_auto_true
      with_readiness_wait do
      expect(page).to have_css p.css_input_street_address
      expect(page).to have_select p.css_driver1_years_lived_there, selected: years_at_residence_option
      expect(page).to have_select p.css_residence, selected: residence_option
      expect(page).to have_field p.css_vehicle1_parked_at_mailing_address_false, checked: true
      expect(page).to have_field p.css_homeowner_insurance_true, checked: true
      expect(page).to have_field p.css_add_violation_true, checked: true
      expect(page).to have_field p.css_add_insurance_claim_true, checked: true
      expect(page).to have_field p.css_add_driver_true, checked: true
      expect(page).to have_field p.css_add_auto_true, checked: true
      expect(page).to have_error_fields

Feature spec

Always aiming to write readable specs

require 'spec_helper'

feature 'Consumer adds additional info' do

  include FullformSetupHelper
  include AutoPoliciesHelper, FullformAdditionalStepHelper, ExitPageHelper

  let!(:policy)  { FactoryGirl.create(:auto_policy, :with_additional_auto_flag, arrival: arrival) }
  let!(:vehicle) { FactoryGirl.create(:polk_vehicle, :with_year_make_and_model) }
  let!(:insurer) { FactoryGirl.create(:insurer, :with_insurer_insurance_type) }
  let(:additional_step_path)  { '/auto_policies/fullform/s2_additional' }
  let(:p) { }

  before :each do
    FactoryGirl.create_list(:tip, 5)
    FactoryGirl.create_list(:auto_insurance_term, 5)

    visit_ready auto_policies_path(current_step: additional_step_path)

  context 'consumer adds a driver', :options do
    context 'correctly', :happy do
      scenario 'sees the name of the new driver on the form', :js do
        first_name, last_name = Faker::Name.first_name, Faker::Name.last_name

        add_additional_driver(first_name, last_name)

        expect(page).to have_content(first_name)
        expect(page).to have_content(last_name)
        expect(policy.drivers.reload.length).to eq 2

    context 'incorrectly', :sad do
      scenario 'does not persist a driver to the database', :js do
        expect{ add_invalid_driver }.to_not change{ Driver.count }

      scenario 'sees field_with_errors', :js do

        expect(page).to have_error_fields

  context 'consumer adds a vehicle', :js, :options do
    context 'correctly', :happy do
      scenario 'sees the vehicle year-make-model for the added vehicle' do
        add_additional_vehicle(vehicle.year, vehicle.make, vehicle.model)

        expect(page).to have_content("#{vehicle.year} #{vehicle.make} #{vehicle.model}")
        expect( eq(2)

    context 'incorrectly', :sad do
      scenario 'does not persist an auto to the database' do
        expect{ add_invalid_additional_vehicle }.to_not change{ Auto.count }

      scenario 'sees field_with_errors' do

        expect(page).to have_error_fields

  context 'consumer adds a violation', :options do
    context 'correctly', :happy do
      scenario 'persists the additional violation', :js do

        expect(Violation.count).to eq(1)

      scenario 'sees the violation added', :js do

        expect(page).to have_content('Violation 1')

    context 'incorrectly', :sad do
      scenario 'sees field_with_errors', :js do

        expect(page).to have_error_fields

      scenario 'does not persist a violation to the database', :js do
        expect{ add_invalid_violation }.to_not change{ Violation.count }

  context 'allow only one driver association form', :js, :options do
    before :each do
      visit_ready auto_policies_path(current_step: additional_step_path)

    scenario 'hides add buttons' do

      expect(page).not_to have_selector p.css_violation_add, visible: true

    scenario 'brings back add buttons on cancel' do
      with_ajax_wait{ find(p.css_remove_driver2).click }

      expect(page).to have_selector p.css_add_driver, visible: true

    scenario 'brings back add buttons on successful save' do

      expect(page).to have_selector p.css_add_claim

    scenario 'does not bring back add buttons on failed save' do

      expect(page).not_to have_selector p.css_add_claim, visible: true

Ruby Flavored Design

Ruby Flavored Design.
– Assign instance variables in initialize methods (Define variables in one place only)
– Wrap instance variables with attrs (Define Behavior not Data)
– Break down complex calculation to reveal hidden methods (Decompose for simplicity)
– Remove dependencies from methods for other: Class Names, Method Names, Parameters, Parameter Order (Decouple to avoid dependencies)
– Remove 2nd order dependencies to follow the Low of Demeter (Reduce coupling)
– Removing Class Name dependency: Move Class to instance variable in initialize (Reduce Coupling through Dependency Injection of the object)
– Remove Method Name dependency: Wrap other_object.method in method (Reduce Coupling)
– Remove Parameter Order Dependencies: Change parameter list to hash for named keys (Reduce Coupling)
– Remove Parameter Dependencies: Provide defaults when possible (Reduce Coupling)
– Choose dependency Direction: Choose the object that changes less, e.g. ruby vs. rails vs. local code (Dependency Injection).
– Choose dependency Direction: Choose abstract classes over concrete ones (Dependency Injection)
– Choose public or private interfaces: Reflect the need and control the dependencies (Dependencies)
– Use Delegation to avoid method chaining (Law of Demeter)
– Use Duck Typing to increase flexibility (Reduce Cost of Change)
– Use Abstract Superclasses (“Vehicles”) but ONLY instantiate through their subclasses (‘’)
– Use Inheritance to share universal common behavior (Inheritance)
– Use Modules to share specific common behavior (Modularity)
– Combine Objects with composition (Composition)
– Test public interfaces (Testing)

Basic Selenium Test

A basic template for reference

# filename: search.rb

require "json"
require "selenium-webdriver"
require "rspec"
include RSpec::Expectations

describe "Search" do

  before(:each) do
    @driver = Selenium::WebDriver.for :firefox
    @base_url = ""
    @accept_next_alert = true
    @driver.manage.timeouts.implicit_wait = 30
    @verification_errors = []

  after(:each) do
    @verification_errors.should == []

  it "test_search" do
    @driver.get(@base_url + "/?gws_rd=ssl")
    @driver.find_element(:id, "lst-ib").clear
    @driver.find_element(:id, "lst-ib").send_keys "elemental selenium tips"
    # ERROR: Caught exception [ERROR: Unsupported command [selectWindow | null | ]]
    (@driver.find_element(:link, "Tip Archive - Elemental Selenium").text).should == "Tip Archive - Elemental Selenium"

  def element_present?(how, what)
    ${receiver}.find_element(how, what)
  rescue Selenium::WebDriver::Error::NoSuchElementError

  def alert_present?()
  rescue Selenium::WebDriver::Error::NoAlertPresentError

  def verify(&blk)
  rescue ExpectationNotMetError => ex
    @verification_errors << ex

  def close_alert_and_get_its_text(how, what)
    alert = ${receiver}.switch_to().alert()
    alert_text = alert.text
    if (@accept_next_alert) then
    @accept_next_alert = true

Good Ideas

I’m going to use this post to collect good ideas.

I’m calling it “good ideas” instead of ‘best practices’, ‘rules’, guidelines’, etc as they all other other connotations
The idea is to have a good idea… and then real world examples of it “in action”.

1. Small commits are good
A – 09/21/2015 – everquote
I broke up some simple changes into two commits as the changes were unrelated.
Then CI broke due to one of the file changes
As that file change was in its own commit I was able to revert that commit on its own and continue.

2. One assertion per test
Error text should say “must be numeric” in red.
1. Check the text
2. Check the color of test text.
This one if only one of things is not true the error message will be more specific.

sed and awk. my new best friends and I are going for longer walks

Here’s our latest trip!

$ cat
sed_test_case_html_to_ruby() {
printf "# File: $file_to_convert\n"
cat $file_to_convert | tail +$header_number_of_lines |
sed -E '
s/# #/#/
s/^##/# /' |
awk '{if($0=="click" || $0=="submitAndWait" || $0=="check" || $0=="open" || $0=="waitForElementPresent" || $0=="assertElementPresent" || $0=="waitForVisible" || $0=="clickAndWait" || $0=="pause" || $0=="submit" || $0 =="assertVisible")
{getline n;printf "%s(%s)\n", $0, n}else{print}}' |
awk '{if($0=="fill_in" || $0=="select"){getline n;getline n2; printf "%s(%s, %s)\n", $0, n, n2}else{print}}' |
sed '
/open(/ {
}' |
sed '/^$/d' |
sed $'
/^waitForVisible/ {
s/)$/).to be_visible\\\n/
/^waitForElementPresent/ {
s/)$/).to be_present\\\n/
s/^storeConfirmation/close_alert_and_get_its_text/' |
sed '/css=/  {
/link=/  {
/(\/\// {
/fill_in(/ {
s/, )/, "")/
s/, /, with: /
s/, with: #/, with: "") #/
}' |
awk '{if ($1 ~ /^select\(/ ) {printf "SELECT(%s %s\n", $2, $1} else{print}}' |
sed '/^SELECT/ {
s/) select(/,/
s/,/, from: /
/click(/ {
}' |
awk '{if ($1 ~ /^>>>>>/ ) {printf "it \"";print $0"\" do"} else{print}}' |
sed $'/it/ {
s/it " /it "/
s/Begin //
}' |
awk '{if ($1 ~ /^<<<<</ ) {printf "  end";print ""} else{print}}' |
awk -F"(" '{if ($1 ~ /^assertVisible/ ) {printf "expect( be_visible\n",$2;print ""} else{print}}' |
awk '!/^it/ && !/^end/ {printf("  %s\n", $0);next};1' |
awk '!/^before/ && !/^end/ {printf("  %s\n", $0);next};1' |
awk -F"(" '{if ($1 ~ /    expect/ ) {printf "    expect(";printf $2"\n"} else {print}}' |
awk -F"(" '{if ($1 ~ /^    end$/ ) {printf "  end\n    it \"next step\" do\n"} else {print}}' |
awk 'BEGIN {print "scenario \"'"$file_to_convert"'\" do"} {print} END {printf "  end\nend\n"}' |
sed '
/^      end$/d
s/select(, from:  select(css_vehicle1_auto_make/select(auto_make_1, from: css_vehicle1_auto_make)/' |
# Above s/select... is a brute force hack to fix one line I can't figure out with sed or awk
sed $'
s/select(auto_make_1, from: css_vehicle1_auto_make)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_make_2, from: css_vehicle1_auto_make)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_model_1, from: css_vehicle1_auto_model)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_submodel, from: css_vehicle1_auto_submodel)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_make_1, from: css_vehicle_make)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_make_2, from: css_vehicle_make)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_model_1, from: css_vehicle_model)/with_ajax_wait do\\\n      &\\\n    end\\\n/
s/select(auto_submodel, from: css_vehicle_submodel)/with_ajax_wait do\\\n      &\\\n    end\\\n/' |
awk '{if (NR != 2) {print}}' |
sed $'
s/^[[:space:]]*it/  end\\\n  it/
/expect(.*).*to be_visible/ {
s/expect(/with_ajax_wait do\\\n      &/
s/be_visible/&\\\n    end/

Identifying Web Elements for UI Automation

Identifying web UI elements at everquote in rails based applications is interesting.

The following facts and approaches have emerged:

– Our forms flip between new and edit.  One of the consequences is that we have to force 1 required field to be empty for SAD flows to work correctly.
– All database backed fields should use css NAMES for identification instead of ID.  This is because database backed elements in rails automatically generate the NAME attributes and thus are automatically consistent regardless of placement and regardless of programmer preference or style
– The mixed `css=` and `name=` are best managed by just using `css=` in the Selenium IDE.
– set speed and deleteAllVisible cookies steps didn’t seem to really help.
– for select dropdowns, waitforElementPresent and select should use the same format for identifying the select
– Most of the “action” buttons and links should have human readable characteristics, e.g. `css=a.add_vehicle` is clearly a link for adding a vehicle.  Similarly `css=a.remove-violation[data-method=delete]` is clearly a “delete violation” link.
– delete buttons should be selected with `data-method=delete` when that attribute it is available on the element.
– selection should generally not be based on layout tags such as `div`, `td`, `span`, etc.  `li` is somewhat of an exception as lists of items are a generic data form. Exceptions to the above are used for scoping if nothing else currently exist.


Screen Shot 2015-08-10 at 8.40.53 AM

Introducing QA in an Agile environment

Useful for references for my on-going work at
Whole Team Approach – Page 10
Scrum/Kanban – Page 12
Retrospectives – Page 14
CI – Page 14
Iteration planning – Page 16
Organizational Options for Independent Testing – Page 22
Communicating Test Status, Progress, and Product Quality – Page 23
The Role of a Tester in an Agile Team – Page 26
Testing Quadrants, Test Levels, and Testing Types – Page 29
The Role of a Tester – Page 39

QA Implementation
Quality Funnel (Page 14)
Summary (Page 24)


public ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtvkxdjkyTLzz3/Xdkl08u0uvXoipruTylZGIEBqDGEUW1aUwSYuS7yu02uEW2oVCsx/uNGFQevqUzWALEf84MRdjSrTcywEMDYpwIhJ0aIwEnVst1pMWuUlS22pSq1GXTgvyRfiJGFqEM4DrolkzCgvGmSpchclOMkt10dtfelKXmaW6WcvJSDiBDruV/VQDrQbxczr9Tz4eAH5ZshOXNlyPElIwLFuDeBnXot2AS107CWNBxK6TRYWY4L5mHBt/Cq9erGKwssuObXbPHXPOW5BE8gM5ukIwxlCVajIr6GZCj53K8ecd8KVKocNGiqtvikbWvaRIJSAf/CYOEGs1b

Insurance Terms

At the following terms are useful to know:

  • Assigned Risk Plan

    An auto insurance plan managed by the state for those who aren’t able to get conventional liability coverage due to negative driving records. Drivers are put in a residual market and insurance companies are designated to write policies for these individuals at higher prices.

  • Collision Coverage

    Coverage that pays for damage to the insured’s vehicle as a result of a collision/impact with another vehicle or object. The insured has the responsibility for paying the deductible when the damage is repaired. Learn more on the EverQuote blog: What is Collision Coverage and What Doesn’t It Cover?

  • Collision/Damage Waiver (CDW)

    A waiver that provides an individual who rents a car with protection in the case of an accident. The waiver states that if something happens to the rental car, the rental company will not make a claim against the renter. Some exceptions apply, including if the renter drives under the influence. The cost of a CDW varies by company. Learn more on the EverQuote blog: Should I Get Insurance When Renting a Car?

  • Combined Single Limit (CSL)

    An auto insurance policy that has a single amount limit for liability payment for bodily injury and property damage. It differs from a split limit policy, which has different limits for bodily injury per accident, per person, and for the property damage per accident.

  • Comprehensive Coverage

    Coverage that is used to pay for damage resulting from hazards other than collisions, such as fire, windstorms, explosions, or contact with an animal. Similarly to collision coverage, with comprehensive coverage, the insured is responsible for paying the deductible when their vehicle is replaced or repaired.

  • Comprehensive Loss Underwriting Exchange (CLUE)

    Used by insurance companies to access the insured’s claims information when rating or underwriting a policy. It is inclusive of information such as the type of loss, the date of the loss, the vehicle description, and the amounts paid.

  • Coverage Forms

    Attachments to an insurance policy that are used to complete the policy’s coverage. Also know as endorsement forms.

  • Declarations Page

    A section of an insurance contract containing details such as the description, name, and location of insured property. It also includes addresses and names of the policyholders, the time span for which the policy is in place, the amount of coverage, and the premiums payable. Also known as a “dec sheet.”

  • Declination

    When an insurer decides to refuse coverage to an individual after their insurance application has been evaluated. Some states have rules in place that prevent insurers from declining an application based on poor credit or discriminatory factors.

  • Deductible

    A fee that has to be paid by the insured for covered losses before the insured’s insurance company will pay out for a claim. Deductible amounts can vary from $100 to $1,500. In general, the higher the insured’s deductible, the lower the insured’s premium is likely to be.

  • Deposit Premium

    A deposit paid by a prospective policyholder after an insurance application has been submitted. It is typically the same sum as the first month’s estimated premium or above. The cost is added to the total policy premium.

  • Driver Education Credit

    A discount toward auto insurance premiums for young drivers that is available in some states. Drivers gain eligibility for this credit upon completing a driver education course.

  • Endorsement

    A written agreement that is attached to an insurance policy for the addition or subtraction of coverage. Once it is attached, the original terms of the policy are overwritten.

  • Free Look Period (FLP)

    The period of a policy during which it is possible for the policy to be cancelled by the insured. Typically, the free look period is the first thirty days of the policy, though the number of days differs depending on the state.

  • Independent Agent

    A professional in the insurance field that represents a number of insurance companies. Any single company does not employ them; they simply earn commissions by selling policies.

  • Lapse

    When a privilege or right expires after one party does not fulfill their obligation within the allowed time period. When auto insurance coverage lapses, it could lead to a higher premium for another new policy, since insurers understand that a driver that has maintained the same coverage is far less likely to make an insurance claim than an individual that has allowed their policy to lapse.

  • Liability Insurance

    Coverage for an insured individual’s legal fees and costs in the event they are sued and/or have to pay for property damage, bodily injury, or financial loss that has been caused to others.

  • Loss of Use

    A fee charged by rental agencies that reflects the amount of money the company loses if a car must be repaired after an accident. Learn more on the EverQuote blog: Should I Get Insurance When Renting a Car?

  • Medical Payments Coverage

    An aspect of a standard auto insurance policy that covers funeral bills and medical expenses incurred by the insured and any passengers within the insured’s vehicle in the case of an accident. It does not matter who is at fault.

  • No-Fault Insurance

    Some states have auto insurance laws that make it necessary for companies to cover losses, no matter who caused the accident. See Personal Injury Protection.

  • Personal Injury Protection (PIP)

    Coverage that your insurance company provides for hospital, funeral, and medical expenses that have been caused by a vehicular accident, regardless of who is at fault. Sometimes, it is possible for the insured’s passengers and other expenses to be covered by PIP.

  • Policy Period

    The time span in which an insurance policy applies. The beginning of an auto insurance policy starts and ends at 12:01 am for whatever time zone the insured is in.

  • Premium

    The payment that is necessary to keep an insurance policy in force. Premiums are quoted for either annual or six-month policy periods.

  • Property Damage Liability Coverage

    Coverage that is included in standard auto insurance policies to cover losses incurred as a result of destroying or damaging another person’s property. The policy limit applies, and this kind of coverage is required in the vast majority of states.

  • Replacement Cost

    The cost for the reparation or replacement of damaged or lost property without the allowance of depreciation in value or market value considerations. Guaranteed Replacement Cost coverage is offered by some auto insurance companies, provided that he loss has occurred within 12,000 miles driven or inside the first twelve months of ownership.

  • Residual Value

    The value at which an asset is expected to be at the end of a designated time period. For example, a car valuation at the end of a lease.

  • Split Limit

    A policy with three different amounts as liability payment limits: one for bodily injury per accident, one for bodily injury per person, and one for damage to property that has occurred in an accident.

  • Surcharge

    A rise in the insured’s insurance premium as a result of a moving violation or an at-fault accident.

  • Underinsured and Uninsured Motorist (UM/UIM) Coverage

    Covers the insured’s injuries that result from an accident with a driver that is uninsured, or doesn’t have insurance that adequately covers either party. Standard auto insurance policies provide this form of coverage.

Tests for private methods

I’ve been thinking about this recently as I’ve been writing my own test runner for shell scripts.

I have found myself decomposing longer methods into shorter, private ones (thinking ruby also here), but I’ve found that during the refactor of red-green-refactor I’ve not been using unit tests to ‘drive’ out the code that is in these private methods.

After reflecting on this and reading I think the approach I’ve been using of testing the public interface is ok.  A significant caveat worth remembering is in the answer

is “if your class that does one thing contains extensive code for doing another thing that is required for, but separate from, its primary purpose, that code should live in another class”

TDD for sh

#!/usr/bin/env bash
. 2> /dev/null

do_test () {
  if [[ $# -eq 0 ]]; then
    printf "$fail_color Error - do_test: No parameters provided - Usage is do_test [function_name] \$LINENO [expected result] [optional params]\n"
    exit 1
  elif [[ $# -eq 1 ]]; then
    printf "$fail_color Error - do_test: Two parameters missing - \$LINENO and expected result (other params as needed)\n"
    exit 1
  declare -ig test_runs test_passes test_fails
  local -r function="$1";shift
  local -r line_number="$1";shift
  local failfast="False"
  local debug="False"
  local verbose="False"
  local test_description=
  local test_matcher=
  local expected=
  local pass_on_params=
  local command_not_found=False
  type "setup" &> /dev/null && setup
  # TODO Replace with for loop (initial attempts failed)
  [[ "$1" == "failfast" ]] && failfast="True" && shift
  [[ "$1" == "debug" ]] && debug="True" && shift
  [[ "$1" == "verbose" ]] && verbose="True" && shift
  [[ "$1" == "failfast" ]] && failfast="True" && shift
  [[ "$1" == "debug" ]] && debug="True" && shift
  [[ "$1" == "failfast" ]] && failfast="True" && shift
  if [[ "$1" =~ ^description= ]]; then
    [[ `echo $1 | grep =` ]] && test_description=`echo $1 | sed 's/.*=//'`' ' &&
  if [[ "$1" =~ ^matcher= ]]; then
    [[ `echo "$1" | grep =` ]] && test_matcher="`echo "$1" | sed 's/matcher=//'`" &&
  if [[ $# -eq 0 ]]; then
    printf "$fail_color Error - Function: $function, Line: $line_number \n
do_test: Third parameter missing - expected result\n"
    exit 1
  $function ${pass_on_params[@]} 2> $TMPDIR"/output$$-"$test_runs".txt"
  cat $TMPDIR"/output$$-"$test_runs".txt" | grep -i "command not found" &&
  debug_printf "(debug)"
  if [[ $command_not_found == "True" ]]; then
    record_script_failure "$function"
  elif [[ "$test_matcher" == "==" ]]; then
    [[ "$result" == $expected ]] &&
    record_test_success "$function" ||
    record_test_failure "$function";
  elif [[ "$expected" =~ ^-?[0-9]+$ ]]; then
    [[ "$result" -eq $expected ]] &&
    record_test_success "$function" ||
    record_test_failure "$function";
    [[ "$result" == $expected ]] &&
    record_test_success "$function" ||
    record_test_failure "$function";
record_test_success () {
  [[ $# -eq 0 ]] && no_param_quit $FUNCNAME
  local -r function="$1"
  printf "$pass_color"."$color_end"
  [[ "$verbose" == "True" ]] && printf "$function"
record_test_failure () {
  [[ $# -eq 0 ]] && no_param_quit $FUNCNAME
  local -r function="$1"
  printf "$fail_color"F"$color_end"
  function_exists? "$function" &&
    error_messages=$error_messages"$fail_color""$test_description""Line: $line_number - \
'$function ${pass_on_params[@]}' failed:\n\
Expected: $expected\n\
Received: $result $color_end\n\n" ||
    error_messages=$error_messages"$fail_color""Line: $line_number: \
Function '$function' is undefined\n"
  [[ "$failfast" == "True" ]] && failfast "Test" $error_messages
record_script_failure () {
  [[ $# -eq 0 ]] && no_param_quit $FUNCNAME
  local -r function="$1"
  err=`cat $TMPDIR"/output$$-"$test_runs".txt"`
  printf $err
  error_messages=$error_messages"$fail_color""Line: $line_number: \
Error within function '$function', getting \"command not found\" in $err \n"
  [[ "$failfast" == "True" ]] && failfast "Script" $error_messages
failfast () {
  printf "\n$1 error & failfast set to exit immediately.\n$2\n" && exit 1

no_param_quit () {
  printf "\nError - 1 parameter required for: $1 - exiting\n" && exit 1
function_exists?() {
    declare -f -F $1 > /dev/null
    return $?
debug_echo () {
  [[ "$debug" == "True" ]] && echo "$1"
debug_printf () {
  [[ "$debug" == "True" ]] && printf "$1"
13:11:33 durrantm Castle2012 /home/durrantm/Dropbox/_/sh__sed__awk/euler 

Screenshot from 2015-04-02 13:25:18

Javascript Best Practices

## Javascript Best Practices

# Spaces around operators
5 + 4

# Space after every comma
Good: 5, 6, 7
Bad: 5,6,7

# One statement per line

# Always use braces for blocks
if a {
Bad: if a

# Use {‘s at the end of a line
if a {
if a

# Use line comments within code
// these are
// comments
/* these
are comments */

# Declare variables at the start of functions (function scope)
var x = 0;



# For comparisons use === or !==(objects, same type, preferred use) or use == or !=(values, type doesn’t matter) instead of =
if a === b

if adr1 == adr2

if a = b

if adr1 = adr2

# Always break out of of switch case statements
switch(expression) {
case n:
code block
case n:
code block

switch(expression) {
case n:
code block
case n:
code block

Use a global variables to namespace an application

MyAmazoApp.recently_viewed = 1
recently_viewed = 1

Improving my vim

:10,12m5 # Move (dp) lines 10,12 to line 5
:20,40co10 # Copy (yp) lines 20-40 to line 10
:.,$ d # Delete from currrent line to end of file
:20,30 m $ # Moves lines 20-30 to end of file
:,+20 y # yank current 20 lines

:x # write if modified and quit.
:100r y.y # read in file at line 100
:e file # edit another file
:e # # edit secondary file
:e % # edit primary file
:w %.backup # save a backup with [current filename].backup
[ctrl]^ # Switch between primary / secondary files !

:s/old/new/g # For all occurances, current line
:%s:ENTER:& # "wrap" ENTER in italics, entire file, first line instances
:%s/ */ / # collapse multiple any length to single spaces only
:%s/^/>--- # Add >-- at the start of all lines
:1,10s/old/new/g # For lines 1-10 of the file
:;+10s/old/new/gi # i = ignore initial case
:1,100s/a/b/gc # c = confirm each one (y[enter] or [enter])
:g/pattern/s/a/b/g # within lines that have /pattern/ ...
:g/overdue/s/$/ NOW! # within ... Append NOW! to lines with "overdue" in them

Patterns (regular expressions).
/p.p # pep pap pop
/p.*p # pep peep seeeeep soop pp
/^q # q quick quote qin
/^qn$ # qin
/^\^ # ^chr
/h[aeiu]ll.* # hall hell hill hull hall hilly ...
/h[ae][ae]l # heel
/house\|home # hightlights all instances of house or home & goes to first
/house.*home # Only lines with house followed later by home
/house.*home\|home.*hous # Lines with both (either house then home, or home then house)
/[house]\|[home] # ALL h's, i's, o's, m's, e's, u's
/[house|home] # ALL h's, i's, o's, m's, e's, u's

Window Splits (without tmux):
:new # New horiz pane with new file
:vnew # New vert pane with new file
:split # Same file, new h pane
:vsplit # Same file, new v pane

vi +100 x.x # open at line 100
vi +/command x.x # open at text "command"
"1yy yank to buffer 1
"1p put buffer 1
mx = mark x
`x = goto x
:!ls # unix shell and ls command
:r !ls # unix ls and pipe output into file.
:1,10!zsort # Apply unix sort command to lines 1,10 and re-write them
cc # Change whole line
:set paste/nopaste # Stop all the text indenting on paste!
vimdiff a.rb b.rb # Better than diff

awk 1sies

One Liner awkisms

printf "Matching character:\n"
awk '/2/ {print}' numbers.txt # all lines with character "2"
printf "\nField 2 matches '2':\n"
awk '$2 - /^2$/ {print}' numbers.txt # all lines with field#2 matching "2"
printf "\nlines 1-5:\n"
awk 'NR == 1, NR == 5 {print}' numbers.txt # lines 1-5 of file
printf "\nfield 2 > 10:\n"
awk '$2 > 10' numbers.txt # 2nd field > 2
printf "\nx\/y\n"
awk '{print $1/$2, $2/$3, $3/$4, $3/$7}' numbers.txt
printf "\nMatching '16'\n"
awk '/16/ {print}' numbers.txt # Entire row when there is a string match
printf "\nMatching '16' all fields, otherwise print NO - field4\n"
awk '/16/ {print;next} {print "NO - "$4}' numbers.txt # Entire row when there is a string match
printf "\nAdd ++++'s at the start of lines with \"16\" in them:\n"
awk '/16/{sub(/^/, "++++ "); print;next;}{print}' numbers.txt
printf "\nRandom Numbers:\n"
awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'
printf "\nlong param 2's:\n"
awk 'length($2)>1' numbers.txt
printf "\nshort lines:\n"
awk 'length<21' numbers.txt
printf "\nSum up ALL the 2nd fields...\n"
printf "2 + 4 + 6 + 8 + 10 + 12 + 14 + 16 + 18 =\n"
awk '{ sum += $2 } END { print sum }' numbers.txt
printf "\nLine Numbers:\n"
awk '{print FNR "\t" $0}' numbers.txt
printf "\nPrint line 5 and exit:\n"
awk 'NR==5 {print;exit}' numbers.txt
printf "\nCount lines (emulates wc -l)\n"
awk 'END{print NR}' numbers.txt
printf "\nAdd all fields in all lines and print the sum !\n"
awk '{for (i=1; i<=NF; i++) s=s+$i}; END{print s}' numbers.txt
printf "\n------------------------\n"
printf "\nPrint each rows total:\n"
awk '{s=0; for (i=1; i<=NF; i++) s=s+$i; print s}' numbers.txt
printf "\nPrint first 4 lines of file (emulates behavior of head)\n"
awk 'NR < 5' numbers.txt

Shell Scripting for rvm ruby listing

Continuing to find nice ways to use quick shell scripts as part of ruby test automation:

Wrote this today (Sunday) in prep for using it at work next week.

function make_sure_rvm_rubies_installed() {

rvm list > $TMP/local_ruby_versions.txt
local_ruby_versions=(1.8.7 1.9.3)

for version in “${local_ruby_versions[@]}”
cat $TMP/local_ruby_versions.txt | grep -q $version
if [ $version_search_result = 0 ]
echo “Required RVM Ruby version $version confirmed as present on this machine”
echo “*** EXITING SMOKE TEST *** – not all required ruby versions are present in RVM”
echo “Please install RVM ruby version: $version and then re-run this program”
if [ $? = 0 ]
echo “All required Ruby Versions confirmed as present locally”
rm -f $TMP/local_ruby_versions.txt


Velocity, New York, September 2014

Amazing 3 day conference on Performance and Devops.

Some Highlights:

  • CD (Continuous Deliver) is happening at several (big) places, e.g. Twitter, Android, etc.
  • Feature switches are a great way to manage the deployment process.
  • Service Oriented Architectures are all the rage everywhere but amazingly hard to test.
  • New HTML <picture> tag to help with bandwidth on Mobile Devices.
  • Lessons from – monitor, monitor, monitor.