Agile Transformation and Management

Many companies have gone or are undergoing Agile transformations.
There is typically a large focus on the dramatic change for regular ‘workers’ in how they do their daily activities.

One item that can easily be over-looked however is the change in daily practices for Management.  Some new organizations have eliminated all ‘supervisor’ and ‘manager’ roles, just leaving developers and a director.  Other, existing organizations that are transforming to Agile have difficult decisions to make about how to retool their management.

Failing to recognize and change can lead to management continuing to use waterfall approaches and not understanding the new empowerment model for workers.

Some of the mis-matched approaches seen in this area are:

  • Using personal checklists to make sure a project is on track
  • Using personal relationships to get non-planned work done
  • Adding ‘important and urgent’ tasks without going through the full process
  • Praising off-board work as heroic
  • Discussions on team effectiveness without the team present
  • Assigning or changing team resources without full team involvement
  • Using traditional project management skills to try and manage the Agile process
Advertisements

Tech Traveler Tips

Tips for Tech for Frequent Travelers

  • Multiple ipods if used
  • Audio cable in every bag
  • Install airline mobile apps
  • Charge check the night before
  • Volutz USB cables in every bag
  • Install travel booking mobile app
  • Extra laptop charger just for travel
  • Kindle for all books and magazines
  • Clear cosmetic bag for cable storage
  • Battery for mobile device charge ups
  • Bluetooth noise cancelling headphones
  • USB wall power plug adapter in every bag
  • Check comfort seat upgrades 2 weeks ahead
  • Use Airplane Mode anywhere to save battery life

The Ultimate Quality Challenge

The Ultimate Quality Challenge has become clear to me.
Here’s some of the things that I’ve found it is NOT about:

  • Programming
  • User Experience
  • Standards and Guidelines
  • Agile Workflows
  • User Acceptance Testing

Don’t get me wrong, all the above are critical to Quality Engineering.
However I am increasingly finding that the Ultimate Quality Challenge is one thing – hiring competent and passionate quality engineers.  This is a prerequisite to all of the above quality activities – without actual people, nothing is implemented (even automation!)

Hiring engineers in the quality space is very challenging for a number of reasons:

  • Historically QE was QA and meant manual testing, typically a lower job grade
  • Quality Engineering now means automation with different skill requirements
  • The majority of engineers like to work with application code, not tests only
  • Quality Engineers may suffer from several ‘second class citizen’ issues
  • Compensation may lead the best and brightest to switch to app dev roles
  • Peer respect may lead some to switch to app dev roles as they become skilled
  • Availability of QE Engineers for hiring is extremely limited (2017)
  • Current automation engineering differs from new javascript practices
  • Quality Engineering is often not championed as a cool and useful thing

I want to help change that!
Some of the things I am doing:

  • Active on sqa.stackexchange.com asking and answering questions to promote good quality practices.  I am #1 world-wide in 2017 !
  • Active in Ministry of Testing slack community
  • Presenter on Quality at work, local meetups, national and international conferences

ES6: Destructuring, Object Literal Enhancement and the Spread operator

Destructuring

Scoping an object locally

From an object

    var {pref1, pref2} = user  // user is object w/ keys pref1, pref2

From a functions arguments

    var function_x = ({firstname}) => {
      full_name = `${firstname} of boston`
    }

From an array

var [first_town] = ['Boston', 'Salem', 'Ham']  // 1st_town= Boston
var [,,last_town] = ['Boston', 'Salem', 'Ham']  // lst_town= Ham

Object Literal Enhancement

I’m guessing that name is going to change…
The opposite of destructuring.
Puts objects and methods together.

Objects from variables

var shell='bread'
var filling='butter'
var sandwich = {shell, filling}  
// New object 'sandwich' with contents
// {shell: 'bread', filling: 'butter'}

Object methods from variables

// Method is 'toast'
var toast = function() { console.log('Toast it for {time}') }
var toastedSandwich = {shell, filling, time}
toastedSandwich.toast

Spread Operator “...

Array values

The actual values from an array (not the array itself)

var arr1 = ['Buick', 'Ford']
var arr2= ['Edsel', 'Dodge']
var arr3 = [...arr1, ...arr2]

Function argument values as an array

function direction(...args) {}

Object Values

The key-value attributes from an object, not the object itself, e.g.

obj1={a:1, b:2}
obj2={c:3, d:4}
obj3={...obj1, ...obj2}

 

More Javascript for testers

Objects have prototype methods which are shared for all instances

Useful for methods that apply to all instances

Person.prototype.some_method_name=  function() {
  commands;
};

Avoid for properties that store state data, e.g. arrays with elements managed by various methods.

When you need to define multiple methods on the prototype you can use the format below, however they should also define the constructor as shown so that the prototype is Person and not just Object:

Person.prototype = {
  constructor: Person,
  first_method: function() {...},
  second_method: function() {...};  
};

You can add methods to prototypes for all objects including builtins objects such as Array, String, etc.

Inheritance is through above Prototype Chain, e.g.

var instance2 = Object.create(instance1, {
  name: {
    value: "some_new_thing",
    ...
    }
});

next

IIFE – Immediately Invoked Function Expression

Commonly used in javascript for modules.
Note surrounding parens and parens at end

Module Pattern

var person = (function() {
  var age = 25;  // This is private
  return { ... } // These are closures and are public 
}());

Revealing Module Pattern

var person = (function() {
  var age = 25;
  function x() {...}
  return { x: x, ...}; // Note same name (x)
}());

Private Members use ‘this’

  this.getAge = function () { return age; };

 

Javascript Goodies

Functions

function declarations

function thing(p1,p2) {
  code
  return value;
}
  • Starts with word ‘function’
  • Not separately assigned to a variable
  • WILL be hoisted and declared at top

vs

function expressions

var thing = function(p1, p2) {
  code
  return value;
};
  • Assigns function with no name (annoymous) to a named variable
  • Will NOT be hoisted to top, will be defined inline

IIFE’s – immediately invoked function expressions

(function(){ /* code */ }()); // Like this
(function(){ /* code */ })(); // or this
– key identifier is surrounding parens – ()
– invoked at actual runtime

Function Overloading

Achieved with functions by examing arguments, e.g.
function abc() {
   if (arguments.length === 0) {     this code; }   
else {
     other_code;   } }

The three ways to use ‘this’ with methods in javascript functions

1 With call
some_function.call(this, "text")

A particular value for ‘this’ and specific parameters

2. With apply
some_function.apply(this, "text")

A particular value for ‘this’ and, specifically, an array for any parameters

3. With bind
some_function.bind(this, "text")
‘this’ is the value for the new function, the rest are named parameters for ‘new’

Object Properties

Common Internal Properties
  • Extensible
  • Prototype
Data Properties, i.e. values
All Data Properties also have two attribute methods:
  • value
  • writeable
or
Accessor Properties, i.e. functions
All Accessor Properties also have two attribute methods:
  • get
  • set
  e.g.
var tree = {
  _name: "Oak",
  get name() {
    console.log("here1");
    return this._name;
    },
  set name(value) {
    console.log('here2'); 
    this._name = value;
  }
};

Retrieving Property Attributes

Object.getOwnPropertyDescriptor()

Constructors and Prototypes

Constructors use ‘new’ to create a new instance of a method.

Functions should be capitalized when they are used as constructors – you will be creating new instances of them with ‘new’.

All functions have an internal prototype property
You can check for it with object.hasOwnProperty(name)

Rubyists may find its usage has some similarities to Ruby’s class level methods.

When an object (function w/new constructor) has methods that are shared by all instances use a prototype function for the Object

YourObject.prototype.yourFunctionName = function() {...}

When an object (function w/new constructor) has attribute values that are shared by all instances use a prototype attribute for the Object

YourObject.prototype.yourVariableName = value

 

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 – https://cucumber.io/
    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.

https://httpd.apache.org/docs/2.4/programs/ab.html

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 !

WTF

World of Testing Forums

Mega Meta List of Automated Software Testing Information: https://www.smartsheet.com/automation-testing-software

My Favorites

https://testing.googleblog.com/
Google’s blog – mind blowing information about flaky tests
Highlights:
“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.”

http://www.ontestautomation.com/
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.”

https://www.joecolantonio.com/2017/05/25/grass-greener-testers/
“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)

http://angryweasel.com/blog/
“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

Searching:

/   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 (http://git-scm.com/book/en/Git-Basics-Tips-and-Tricks)
  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 = Time.now + max_wait_time.seconds
  while true
    return if yield
    if Time.now > wait_until
      raise "Condition not met: #{condition_name}"
    else
      sleep(polling_interval)
    end 
  end 
end

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) { FactoryGirl.build(: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) { PageObject.new }
  before :each do
    setup_three_step_minimal_foundation
    setup_landing
    setup_landing_page('myquote_non_sem', config_set, mobile: false)
    setup_auto_page('three_step_minimal_foundation')
    setup_exit_page('myquote_non_sem', config_set, layout: 'empty_page_with_theme', mobile: false)
  end

  context '3_step_minimal_foundation UI test', :js do
    before :each do
      visit_ready landings_path
    end
    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
    end

    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
        end
      end
      scenario 'now we are on stage#1, the auto_policies path', :happy do
        expect(current_path).to eq auto_policies_path
      end
      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
          find(p.css_submit_form).click
        end
        find(p.css_has_license).click
        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
          find(p.css_submit_form).click
        end
        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
        find(p.css_submit_form).click
        end
        expect(page).to have_css p.css_quotes
      end
    end
  end

  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
      end
    end

    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
        find(p.css_submit_form).click
      end
      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
    end

    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
        find(p.css_submit_form).click
      end
      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
    end

    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
      end
      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
        find(p.css_submit_form).click
      end
      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
    end
  end
end

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) { PageObject.new }

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

    visit_ready auto_policies_path(current_step: additional_step_path)
  end

  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
      end
    end

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

      scenario 'sees field_with_errors', :js do
        add_invalid_driver

        expect(page).to have_error_fields
      end
    end
  end

  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(policy.autos.reload.length).to eq(2)
      end
    end

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

      scenario 'sees field_with_errors' do
        add_invalid_additional_vehicle

        expect(page).to have_error_fields
      end
    end
  end

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

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

      scenario 'sees the violation added', :js do
        add_valid_violation

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

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

        expect(page).to have_error_fields
      end

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

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

    scenario 'hides add buttons' do
      find(p.css_violation_add).click

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

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

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

    scenario 'brings back add buttons on successful save' do
      add_valid_violation

      expect(page).to have_selector p.css_add_claim
    end

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

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

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 (‘Motorcycle.new’)
– 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 = "https://www.google.com/"
    @accept_next_alert = true
    @driver.manage.timeouts.implicit_wait = 30
    @verification_errors = []
  end

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

  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"
  end

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

  def alert_present?()
    ${receiver}.switch_to.alert
    true
  rescue Selenium::WebDriver::Error::NoAlertPresentError
    false
  end

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

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

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
Examples:
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
Example:
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_one_test_case_html_to_ruby_functions.sh
sed_test_case_html_to_ruby() {
file_to_convert="$1"
header_number_of_lines="14"
printf "# File: $file_to_convert\n"
cat $file_to_convert | tail +$header_number_of_lines |
sed -E '
/<td><\/td>/d
/<\/tr>/d
s/(<tr>|<td>)//
s/<\/td>//
s/<\/tbody><\/table>//
s/.*<thead>//
s/.*<\/thead><tbody>//
s/(<\/html>|<\/body>)//
s/.*~.*//
s/\${//g
s/\}//
s/\}$//
s/<\!--/#/
s/#<<<<</<<<<</
s/#>>>>>/>>>>>/
s/-->$//
s/[[:space:]]//
s/^type$/fill_in/
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(/ {
s/open(/visit("http:\/\/staging.everquote\//
s/)/")/
}' |
sed '/^$/d' |
sed $'
/^waitForVisible/ {
s/waitForVisible/expect/
s/)$/).to be_visible\\\n/
}
/^waitForElementPresent/ {
s/waitForElementPresent/expect/
s/)$/).to be_present\\\n/
}
s/^clickAndWait/click/
s/^submitAndWait/submit/
s/^storeConfirmation/close_alert_and_get_its_text/' |
sed '/css=/  {
s/css=/&"/
s/)/")/
}
/link=/  {
s/link=/&"/
s/)/")/
}
/(\/\// {
s/\/\//"\/\//
s/)$/")/
}
/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/,$/)/
s/,/, from: /
s/SELECT/select/
}
/click(/ {
s/click(/find(/
s/)/).click/
}' |
awk '{if ($1 ~ /^>>>>>/ ) {printf "it \"";print $0"\" do"} else{print}}' |
sed $'/it/ {
s/it " /it "/
s/>>>>>//
s/Begin //
}' |
awk '{if ($1 ~ /^<<<<</ ) {printf "  end";print ""} else{print}}' |
awk -F"(" '{if ($1 ~ /^assertVisible/ ) {printf "expect(%s.to 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 '
/^$/d
/^      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/
/^[[:space:]]*pause(/d
/^[[:space:]]*$/d
/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.

Example:

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 everquote.com

http://marker.to/VsBhbB

http://marker.to/4JYac9

http://www.istqb.org/downloads/finish/52/138.html
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
http://marker.to/XIMhm2

https://www.scrumalliance.org/system/resource_files/0000/0459/AgileQA.pdf
Quality Funnel (Page 14)
Summary (Page 24)

git

public ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCtvkxdjkyTLzz3/Xdkl08u0uvXoipruTylZGIEBqDGEUW1aUwSYuS7yu02uEW2oVCsx/uNGFQevqUzWALEf84MRdjSrTcywEMDYpwIhJ0aIwEnVst1pMWuUlS22pSq1GXTgvyRfiJGFqEM4DrolkzCgvGmSpchclOMkt10dtfelKXmaW6WcvJSDiBDruV/VQDrQbxczr9Tz4eAH5ZshOXNlyPElIwLFuDeBnXot2AS107CWNBxK6TRYWY4L5mHBt/Cq9erGKwssuObXbPHXPOW5BE8gM5ukIwxlCVajIr6GZCj53K8ecd8KVKocNGiqtvikbWvaRIJSAf/CYOEGs1b m2@snap2web.com

Insurance Terms

At everquote.com 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  http://programmers.stackexchange.com/questions/279117/tdd-red-green-refactor-and-if-how-to-test-methods-that-become-private I think the approach I’ve been using of testing the public interface is ok.  A significant caveat worth remembering is in the answer

http://programmers.stackexchange.com/a/279118/34069

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”