diff --git a/.ruby-version b/.ruby-version index 7fa1d1e..3e3c2f1 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.0.0-p353 +2.1.1 diff --git a/Gemfile b/Gemfile index e1a05c3..5c74aa6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,15 +1,12 @@ source 'http://rubygems.org' -#ruby "2.0.0" -#ruby "1.9.3" - -gem 'cucumber' -gem 'watir-webdriver' -gem 'nokogiri' gem 'bundler' -gem 'headless' gem 'chronic' +gem 'cucumber' +gem 'headless' +gem 'nokogiri' +gem 'rake' gem 'selenium-webdriver' gem 'syntax' +gem 'watir-webdriver' gem 'watir-webdriver-performance' -gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock index 508469a..3fef058 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,7 +5,7 @@ GEM childprocess (0.5.3) ffi (~> 1.0, >= 1.0.11) chronic (0.10.2) - cucumber (1.3.15) + cucumber (1.3.16) builder (>= 2.1.2) diff-lcs (>= 1.1.3) gherkin (~> 2.12) @@ -16,22 +16,23 @@ GEM gherkin (2.12.2) multi_json (~> 1.3) headless (1.0.2) - mini_portile (0.6.0) + mini_portile (0.5.3) multi_json (1.10.1) multi_test (0.1.1) - nokogiri (1.6.2.1) - mini_portile (= 0.6.0) + nokogiri (1.6.1) + mini_portile (~> 0.5.0) rake (10.3.2) - rubyzip (1.1.4) + rubyzip (1.1.6) selenium-webdriver (2.42.0) childprocess (>= 0.5.0) multi_json (~> 1.0) rubyzip (~> 1.0) websocket (~> 1.0.4) syntax (1.2.0) - watir-webdriver (0.6.9) + watir-webdriver (0.6.10) selenium-webdriver (>= 2.18.0) - watir-webdriver-performance (0.2.4) + watir-webdriver-performance (0.2.2) + watir-webdriver watir-webdriver websocket (1.0.7) diff --git a/LICENSE b/LICENSE.md similarity index 95% rename from LICENSE rename to LICENSE.md index 8a74873..1bb7660 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,6 +1,8 @@ The MIT License +=============== Copyright (c) 2014 Modus Create, Inc. +------------------------------------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 9bea2dd..816ea1f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The built in steps in `features/step-definitions/common_steps.rb` cover a variet This approach might not be as pure as some would advocate for BDD, but it strikes a good balance between being implementation specific and being fast to write and execute. -Here's an example of a Cucumber scenario written with the common steps: +Here is an example of a Cucumber scenario written with the common steps: ``` @smoke @regression @desktop @@ -36,7 +36,7 @@ License This test framework is licensed under the (MIT License)[http://opensource.org/licenses/MIT], a permissive free software license. -See the file LICENSE for full copyright and license information. +See the file LICENSE.md for full copyright and license information. Setup on Mac OS X @@ -45,110 +45,137 @@ Setup on Mac OS X Tools Used: ----------- -1. Mac with Sudo Access -2. Xcode with command line tools installed (command line tools can be installed from Xcode -> Preferences -> Downloads) -3. RVM - Optional -4. Ruby 2.0 +1. Mac with `sudo` Access +2. Xcode with command line tools installed. The command line tools can be installed from Xcode -> Preferences -> Downloads +3. RVM (optional) +4. Ruby 2.1.1 5. Watir-Webdriver 6. webdriver-user-agent 7. cucumber -8. homebrew - Optional +8. homebrew (optional) 9. chromedriver Steps To Install: ----------------- -**Install Xcode and then install commandline tools.** ->*Command line tools can be installed from going to Xcode-> Preferences -> Downloads* +### Mac Instructions -**Install RVM** +#### Install Xcode and then install command line tools. - \curl -L https://get.rvm.io | bash +The command line tools can be installed in Xcode by going to Xcode-> Preferences -> Downloads -**Install Ruby** +#### Install RVM - rvm install ruby-2.0.0-p247 + curl -L https://get.rvm.io | bash -*To make this the default ruby on your Mac run the below command. However It is not necessary to make it the default ruby. The gemfile in the folder has the builin workflow to use Ruby 2.0 when you cd into the tests/web folder.* +#### Install Ruby - rvm use ruby-2.0.0-p247 --default + rvm install ruby-2.1.1 -**Install Homebrew** +To make this the default ruby on your Mac run the below command. However you do not need to make it the default ruby for the test scripts to run. The `.ruby-version` file in the folder has the builin workflow to use Ruby 2.1.1 when you cd into the tests/web folder. - ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" + rvm use ruby-2.1.1 --default + +#### Install Homebrew + ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" brew doctor ->*if the above command fails, please follow the steps in the output to fix the errors.* +If the above command fails, please follow the steps in the output to fix the errors. + +Installing Homebrew is optional. These directions use it to install chromedriver, but you could also use `npm` to install chromedriver or install it manually. You can download chromedriver from http://chromedriver.storage.googleapis.com/index.html?path=2.4/ if you want to install it manually. + +#### Install chromedriver -**Install chromedriver** +Install `chromedriver` using Homebrew or npm: brew install chromedriver + # or if you prefer to install chromedriver through npm, do + # npm install chromedriver -g ->*Installing Homebrew is Optional. The only reason I use it is to install chromedriver* ->*You can download chromedriver from http://chromedriver.storage.googleapis.com/index.html?path=2.4/* ->*Unzip and move the driver to anyplace in your path like /usr/local/bin* ->*you can skip the brew install chromedriver below if you download it* ->*Advantage of installing via brew is that you can update it with a single command. (brew update && brew upgrade)* +Unzip and move the driver to any place in your path such as `/usr/local/bin`. -**Install the bundler gem** +The advantage of installing chromedriver via brew or npm is that you can update it with a single command. (`brew update && brew upgrade``) + +#### Install the bundler gem gem install bundler --no-ri --no-rdoc -**Install necessary gems using bundler** +#### Install necessary gems using bundler - cd test bundle install -**Running tests** +### Getting Started (Windows) + +#### Download and Install Ruby +Get Ruby 2.1.1 from http://rubyinstaller.org/downloads/ + +#### Download and install chromedriver + +Get Chromedriver from http://chromedriver.storage.googleapis.com/index.html + +Make sure the chromedriver is in your PATH enviroment variable. - cucumber features +#### From here you can follow the same instructions as above. ->*The above command runs all the tests inside the feature folder but that i snot what you want sometimes. To run single individual tests yo have to specify the line numbers as below* +Running tests +------------- + +You can run the tests directly with the cucumber command, or with a set of preset command line options using the `rake` command. + +### Run cucumber directly + +To run tests directly using Cucumber, simply issue the command: + + cucumber + +The above command runs all the tests inside the feature folder but that is not what you want sometimes. To run single individual tests you have to specify the line numbers as below:. cucumber features/main.feature:217 -This will run the Test scenario at line number 217 +This will run the test scenario at line number 217 in the file `features/main.feature`. -**To see a list of Tasks** +### Run cucumber using `rake` + +Rake uses tasks to collect a set of functions and commands. In this project, it is used to run cucumber with command line options suitable for testing out different groups of tagged features or + +To see a list of tasks, run: rake -T -**To run the whole regression Suite** +To run the whole regression suite, run: - rake regression:all + rake all ->*The HTML report will be saved to the results folder with screenshots of failures if any.* +An HTML report will be saved to the `results` folder with screenshots of any failures. Tips and Troubleshooting: -------------------------- -*Sencha Command integration* +### Sencha Command integration -*Please note that Sencha command needs ruby < 2.0 to be able to build apps successfully.* +If you are using [Sencha Command](http://www.sencha.com/products/sencha-cmd), note that `sencha` may need ruby < 2.0 to be able to build apps successfully. If you have made Ruby 2.0 your default then run the below command before you use the sencha build script. rvm use 1.9.3 ->*You can simply create Alias in your bash profile to run tests. Instead of typing the whole cucumber command create this function in your bashrc or .profile file* - - vi ~/.bash_profile +### Bash alias for running tests - c() { cucumber features/main.feature:"$@" ;} +You can simply create Alias in your bash profile to run tests. Instead of typing the whole cucumber command create this function in your `.bashrc` or `.profile` file: + echo 'c() { cucumber features/main.feature:"$@" ;}' >> ~/.bashrc + . ~/.bashrc -**Save, Exit and source the file or simply restart your terminal** - -**Then you can run the test at line 217 by simply running the command below from the test folder** +Then you can run the test at line 217 by simply running the command below from the test folder: c 217 +### Libxml errors -**If you run into libxml erorrs fix it as suggested in this post** +If you run into libxml erorrs fix it as suggested in this post https://gist.github.com/vparihar01/5856524 - diff --git a/Rakefile b/Rakefile index 4f5e30c..dab7217 100644 --- a/Rakefile +++ b/Rakefile @@ -1,31 +1,65 @@ require 'cucumber/rake/task' + require 'fileutils' FileUtils::mkdir_p 'results' -task :default => 'regression:all' - -namespace :regression do - - Cucumber::Rake::Task.new(:all, 'Regression test suite') do |t| - t.cucumber_opts = "features/*.feature - --format html --out=results/ptp-regression-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html - --format pretty --no-source - --format rerun --out results/ptp-regression-rerun.txt - --tag @regression" - end - Cucumber::Rake::Task.new(:smoke, 'smoke test suite') do |t| - t.cucumber_opts = "features/*.feature - --format html --out=results/ptp-regression-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html - --format pretty --no-source - --format rerun --out results/ptp-smoke-rerun.txt - --tag @smoke" - end - Cucumber::Rake::Task.new(:jenkins_all, 'Regression test suite') do |t| - t.cucumber_opts = "features/*.feature - --format html --out=results/ptp-regression-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html - --format pretty --no-source - --format rerun --out results/ptp-regression-rerun.txt - --tag @regression - 'HEADLESS=true'" - end +task :default => 'all' + +Cucumber::Rake::Task.new(:all, 'Runs all tests') do |t| + t.cucumber_opts = "features/*.feature + --format html --out=results/all-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html + --format pretty --no-source + --format rerun --out results/all-rerun.txt + --tag @regression" +end + +Cucumber::Rake::Task.new(:smoke, 'Runs the smoke test suite') do |t| + t.cucumber_opts = "features/*.feature + --format html --out=results/smoke-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html + --format pretty --no-source + --format rerun --out results/smoke-rerun.txt + --tag @smoke" +end + +Cucumber::Rake::Task.new(:jenkins_all, 'Run all tests for Jenkins CI') do |t| + t.cucumber_opts = "features/*.feature + --format html --out=results/jenkins-all-report-#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}.html + --format pretty --no-source + --format rerun --out results/jenkins-all regression-rerun.txt + --tag @regression + 'HEADLESS=true'" +end + + +Cucumber::Rake::Task.new(:regression, 'Runs tests tagged as regression') do |t| + t.cucumber_opts = "features/* + --format html --out=results/regression-report.html + --format pretty --no-source + --format rerun --out results/regression-rerun.txt + --tag @regression" +end + +Cucumber::Rake::Task.new(:desktop, 'Runs test tagged as desktop') do |t| + t.cucumber_opts = "features/* + --format html --out=results/desktop-report.html + --format pretty --no-source + --format rerun --out results/desktop-rerun.txt + --tag @desktop" +end + +Cucumber::Rake::Task.new(:mobile, 'Runs test tagged as mobile') do |t| + t.cucumber_opts = "features/* + --format html --out=results/mobile-report.html + --format pretty --no-source + --format rerun --out results/mobile-rerun.txt + --tag @mobile" +end + +Cucumber::Rake::Task.new(:tablet, 'Runs test tagged as tablet') do |t| + t.cucumber_opts = "features/* + --format html --out=results/tablet-report.html + --format pretty --no-source + --format rerun --out results/tablet-rerun.txt + --tag @tablet" end + diff --git a/config/cucumber.yml b/config/cucumber.yml index 4368910..791409f 100644 --- a/config/cucumber.yml +++ b/config/cucumber.yml @@ -1 +1 @@ -default: features -t ~@wip -t ~@manual +default: features --tag ~@wip -tag ~@manual diff --git a/features/example.feature.bak b/features/example.feature.bak index aab39c9..6bec0e2 100644 --- a/features/example.feature.bak +++ b/features/example.feature.bak @@ -39,16 +39,23 @@ Scenario: Verify that the Registration Email & Password field is a required Fiel And I must see the "login_email" text field has a class attribute of "ng-invalid-required" And I must see the "login_password" text field has a class attribute of "ng-invalid-required" -@regression @desktop @login +@smoke @regression @desktop Scenario: User views profile page Given I am on the desktop home page Then I must see the page title "example.com" - Given I fill in the text field "login_email" with "anne@example.com" - And I fill in the text field "login_password" with "foobar1234" + Given I fill in the text field "login_email" with "foobar@example.com" + And I fill in the text field "login_password" with "password" And I click the "Login" span And I wait for the "Dashboard" text to be displayed - Given I click the "anne@example.com" link + Given I click the "foobar@example.com" link And I wait for the "Profile" text to be displayed + And I send the "tab" keys + And I send the "06/01/2014" keys + And I send the "tab" keys + And I send the "06/06/2014" keys + And I click the "Save & Continue" span + And I fill in the text field "short_description" with "Modus Kickstart short description" + Then I must see the text "Thank You" displayed @regression @desktop @login @LinkedIn Scenario: User links LinkedIn account to profile via profile page @@ -405,3 +412,5 @@ Scenario: User can successfully delete a kickstart from the dashboard Given I click the "Delete" link And I wait for the "Are you sure?" text to be displayed Given I click the "Yes, Remove" button +Feature: Main automated functional tests + diff --git a/features/main.feature b/features/main.feature index 90af0ac..08220f0 100644 --- a/features/main.feature +++ b/features/main.feature @@ -1,19 +1,22 @@ -Feature: Main automated functional tests +Feature: Main tests -#@smoke @regression @desktop -#Scenario: User views profile page -# Given I am on the desktop home page -# Then I must see the page title "example.com" -# Given I fill in the text field "login_email" with "foobar@example.com" -# And I fill in the text field "login_password" with "password" -# And I click the "Login" span -# And I wait for the "Dashboard" text to be displayed -# Given I click the "foobar@example.com" link -# And I wait for the "Profile" text to be displayed -# And I send the "tab" keys -# And I send the "06/01/2014" keys -# And I send the "tab" keys -# And I send the "06/06/2014" keys -# And I click the "Save & Continue" span -# And I fill in the text field "short_description" with "Modus Kickstart short description" -# Then I must see the text "Thank You" displayed +@smoke @regression @desktop +Scenario: Visit the home page + Given I am on the moduscreate home page + Then I must see the page title "Modus Create | HTML5 Application Development & Training" + Given I click the "Services" span + Then I must see the page title "Services | Modus Create" + +@regression @mobile +Scenario: Visit the home page on a mobile device + Given I am on the moduscreate home page + Then I must see the page title "Modus Create | HTML5 Application Development & Training" + Given I click the "icon-reorder" icon + And I wait for the menu to b displayed + +@wip @tablet +Scenario: Visit the home page on a tablet + Given I am on the moduscreate home page + Then I must see the page title "Modus Create | HTML5 Application Development & Training" + Given I click the "Blog" span + Then I must see the page title "Blog | Modus Create" diff --git a/features/step_definitions/myapp_steps.rb b/features/step_definitions/myapp_steps.rb new file mode 100644 index 0000000..e4cf1ed --- /dev/null +++ b/features/step_definitions/myapp_steps.rb @@ -0,0 +1,66 @@ +Given(/^I am on the moduscreate home page$/) do + puts "Test running against #{BASE_URL}" + @browser.goto(BASE_URL) +end + +Then(/^I must see the page title "(.*?)"$/) do |title| + assert_equal(title,@browser.title) +end + +###### Links +Given(/^I click the "(.*?)" link$/) do |ele| + case + when @browser.link(:id, ele).exists? + @browser.link(:id, ele).click + + when @browser.link(:text, ele).exists? + @browser.link(:text, ele).click + + when @browser.link(:class, ele).exists? + @browser.link(:class, ele).click + + when @browser.link(:href, ele).exists? + @browser.link(:href, ele).click + + else + fail("Link => #{ele} NOT FOUND") + end +end + +###### Span +Given(/^I click the "(.*?)" span$/) do |ele| + case + when @browser.span(:id, ele).exists? + @browser.span(:id, ele).click + + when @browser.span(:text, ele).exists? + @browser.span(:text, ele).click + + when @browser.span(:class, ele).exists? + @browser.span(:class, ele).click + + else + fail("Span => #{ele} NOT FOUND") + end +end + +###### Icon +Given(/^I click the "(.*?)" icon$/) do |ele| + case + when @browser.i(:id, ele).exists? + @browser.i(:id, ele).click + + when @browser.i(:text, ele).exists? + @browser.i(:text, ele).click + + when @browser.i(:class, ele).exists? + @browser.i(:class, ele).click + + else + fail("Icon => #{ele} NOT FOUND") + end +end + +Given(/^I wait for the menu to b displayed$/) do + @browser.ul(:class => "off-canvas-list").wait_until_present +end diff --git a/features/support/env.rb b/features/support/env.rb index d6a72f0..8e4281f 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -33,5 +33,4 @@ def normalize_selector(how, what) end end - -World(MiniTest::Assertions) \ No newline at end of file +World(MiniTest::Assertions) diff --git a/features/support/hooks.rb b/features/support/hooks.rb index 1c3bf9f..c5c36db 100644 --- a/features/support/hooks.rb +++ b/features/support/hooks.rb @@ -1,3 +1,5 @@ +# For more information on writing hooks please read the cuke wiki +# https://github.com/cucumber/cucumber/wiki/Hooks RESULTS_DIR="results" TIMEOUT=180 diff --git a/features/support/paths.rb b/features/support/paths.rb index 2cb1b0a..1ab7e96 100644 --- a/features/support/paths.rb +++ b/features/support/paths.rb @@ -1,13 +1,13 @@ module Paths # Change this to switch environments - #TARGET = :Production + TARGET = :Production #TARGET = :Local #TARGET = :LocalSSL - TARGET = :Guest + #TARGET = :Guest BASE_URL = { - :Production => "http://foobar.example.com/", + :Production => "http://moduscreate.com/", :Local => "http://localhost:8080/", :LocalSSL => "https://localhost:8443/", :Guest => "http://localhost:80/",