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.

Exception to the Rule

Getting error handling right for my linker verification process.

Key Points:

  • rescue Exception is too broad, recsue StandardError is better
  • No need to distinguish errors at this point so rescue StandardError is sufficient to cover all… Standard Errors
  • No need to actually specify standardError as it is the default
  • So with a bit of Less is More, YAGNI and convention over configuration I end up with just:

    def valid_get?
    HTTParty.get(url_address).code.between?(200,399) ? true : false

PS1 ultimate prompt!

🙂  Screenshot from 2014-04-12 14:35:28 

parse_git_branch () {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'
LOCATION='`pwd | sed "s#\(/[^/]\+/[^/]\+/[^/]\+/\).*\(/[^/]\+/[^/]\+\)/\?#\1...\2#g"`'
BRANCH=$COLON'33[00;33m\]$(parse_git_branch)\[33[00m\]\n\$ '

Chain of events.

I’ve been doing more continuous integration lately, both remotely using Jenkins to manage jobs and locally with tools like autotest and Guard.

Sometimes these tools take a bit of configuring to get where one needs to be…

I liked autotest but for new projects I couldn’t get it to run correctly.
I switched to Guard and that worked.
However I was getting an annoying tmux error for each run (“option — q not recognized”)
So I needed to update my tmux installation.
But first I needed to update my Ubuntu version from 12.04 -> 12.10 -> 13.04.  Done.
Then I tried multiple versions of tmux – 1.7, 1.8.4 and 1.9a, compiling locally but couldn’t get any to run correctly.
Finally I found that with tmux I really needed to restart / logout as just closing all terminals apps wasn’t enough.

Entire trip took a day but I had the time available and the upgrades were all tasks on my to-do list for long-term maintenance.  It was also complicated by the fact that frequently when I changed my tmux or .bashrc setup, new terminal windows wouldn’t start.  Sometimes I had to edit my .bashrc file in gedit (basic text editor) to comment out the exec tmux line, just to get terminal access back!

These upgrades are also giving me growl-style notifications which is helpful:

Screenshot from 2014-03-30 09:42:09

Once I got 1.7 working I went back to trying 1.9a and this install was then easy, no restart needed, just exit all terminal windows in between:


$ tmux -V
tmux 1.9a