How to integrate Guice + Cucumber + WebDriver

Hello guys,

Today I am going to post about something that I have been studying. So, in this project you can have an idea of how to implement Dependency Injection using Guice, a Google framework which helps you to reduce the need of new in your Java code. I found only projects that have only the Guice + Cucumber integration or only the Guice + Page Objects, so I think this one might be a good example of how to integrate everything.

Also, the project contains Page Objects and a Driver Factory, so you will be able to include other browsers and implement each one’s singularity when creating the browser, and also you still have the good practices of the POM.

I’ve added comments along the code, but feel free to ask anything or even suggest improvements.

https://github.com/rafaelaazevedo/dog-lightning

Using Spoon with Cucumber

Hi guys,

Today I will post about Spoon which is a framework that I’ve been learning. I hope this helps someone too, because spoon is quite new and doesn’t have too much support if you want to run with Cucumber.

Spoon is a framework to run android reports and Cucumber is a BDD framework.

  • If you are using gradle, you need to open your build.gradle and add:
 classpath('com.stanfy.spoon:spoon-gradle-plugin:1.0.3') {
  exclude module: 'guava'
  }

  • In your app-build.gradle:
plugin 'spoon'

dependencies{
 androidTestCompile 'com.squareup.spoon:spoon-client:1.2.0'
 androidTestCompile 'info.cukes:cucumber-android:1.2.4'
 androidTestCompile 'info.cukes:cucumber-picocontainer:1.2.4'
 } 
  • Create Spoon task in the same file:

spoon {
 debug = true
 if (project.hasProperty('spoonFailNoConnectedDevice')) {
    failIfNoDeviceConnected = true
 }

 if (project.hasProperty('cucumberOptions')) {
    instrumentationArgs = ["cucumberOptions=" + "'${project.cucumberOptions}'"]
 }

}
  • The instrumentation runner:
public class Instrumentation extends CucumberInstrumentation {
@Override
public void onStart() {
    runOnMainSync(new Runnable() {
        @Override
        public void run() {
            Application app = (Application) getTargetContext().
getApplicationContext();
            String simpleName = Instrumentation.class.getSimpleName();

            // Unlock the device so that the tests can input keystrokes.
            ((KeyguardManager) app.getSystemService(KEYGUARD_SERVICE)) //
                .newKeyguardLock(simpleName) //
                .disableKeyguard();
            // Wake up the screen.
            ((PowerManager) app.getSystemService(POWER_SERVICE)) //
                .newWakeLock(FULL_WAKE_LOCK | ACQUIRE_CAUSES_WAKEUP 
| ON_AFTER_RELEASE, simpleName) //
                .acquire();
        }
    });

    super.onStart();
}

}
  • Now you can use gradle command line with spoon task and pass Cucumber arguments. Like this one:
gradle spoon -PspoonFailNoConnectedDevice -PcucumberOptions='--tags @smoke'
      • Or you can use adb command line – without spoon report generation:
adb shell am instrument -w -e cucumberOptions "'--tags @smoke'" 
com.rsouza.test/com.rsouza.test.Instrumentation
  • Instrument arguments
am instrument argument Description
-e count true Count the number of tests (scenarios)
-e debug true Wait for a debugger to attach before starting to execute the tests.
-e log true Enable Cucumber dry-run (same as –e dryRun true)
-e coverage true Enable EMMA code coverage
-e coverageFile “/path/coverage.ec Set the file name and path of the EMMA coverage report
  • Cucumber arguments

https://cucumber.io/docs/reference/jvm#third-party-runners

  • Example: Use Cucumber and adb arguments
adb shell am instrument -w -e log true -e cucumberOptions "'--tags @debug'"
 com.rsouza.test/com.rsouza.test.Instrumentation

Thank you guys ! See you next week 🙂

Gherkin BDD comparison

Hi guys, I will post a research about the BDD engines, it is a bit old (2012), but despite this I found very interesting. I have summarised the relevant informations. The actual language to write tests with BDD is called Gherkin. And it has different implementations adopted to different programming language, the most famous:

Cucumber for Ruby

JBehave for Java

NBehave and SpecFlow for C#

Freshen for Python Behat for PHP

All of them have some common set of supported features but there’re some restrictions and abilities specific to the actual engine. So, we will collect useful features for each listed above engine and present it in some comparable form. Key features to be mentioned are:

  • Documentation availability
  • Flexibility in passing parameters
  • Auto-complete
  • Steps, scenario and feature scoping
  • Complex steps
  • Hooks and pre-conditions
  • Binding to code
  • Formatting flexibility
  • Built-in reports
  • Input data sources support
Grade Criteria
0 No support at all
1 Functionality exists but with serious restrictions
2 Major functionality exists
3 Full-featured support

Documentation Availability

  • Cucumber:
    • Cucumber group on LinkedIn – quite populated place with big number of active discussions
    • Cukes Tutorial Site
  • Freshen – honestly speaking I didn’t find any specialized resourse dedicated to freshen only. Most likely it can be discussed in the more general forums dedicated to BDD in general.
  • JBehave:
  • SpecFlow:
  • Behat:


With this sources to look the documentation of each engine, we can evaluate the criteria and the grades:

GRADE CRITERIA
1 Documentation is available in general (it makes grade 1 at once)
2 Every feature is described and has examples (if it fits it makes grade 2)
3 There’re additional well-grown resources (forums, blogs, user groups) where we can find additional information about the engine

At the end we have:

Engine Documentation availability
Cucumber 3
Freshen 2
JBehave 3
NBehave 1
SpecFlow 3
Behat 3

Other grades:

Flexibility in passing parameters:

Engine Regular expressions support Tables support Multi-line input support Extra features
Cucumber 3 3 3 0
Freshen 3 3 3 0
JBehave 2 3 0 3
NBehave 2 3 0 2
SpecFlow 2 3 3 2
Behat 3 3 3 0

Auto-Complete:

Engine Auto-complete support
Cucumber 1
Freshen 1
JBehave 1
NBehave 1
SpecFlow 3
Behat 1

Step Scenario and feature scoping:

Engine Tagging support Scoped steps support
Cucumber 3 0
Freshen 3 0
JBehave 3 1
NBehave 0 0
SpecFlow 3 3
Behat 3 0

Complex Steps:

Engine Composite steps
Cucumber 3
Freshen 3
JBehave 3
NBehave 2
SpecFlow 2
Behat 3

Hooks and pre-conditions:

Engine Backgrounds Hooks
Cucumber 3 3
Freshen 3 3
JBehave 1 1
NBehave 0 1
SpecFlow 3 3
Behat 3 3

Binding Code:

Engine Binding to code
Cucumber 2
Freshen 3
JBehave 3
NBehave 3
SpecFlow 3
Behat 2

Formatting Flexibility:

Engine Formatting
Cucumber 3
Freshen 3
JBehave 1
NBehave 3
SpecFlow 3
Behat 3

Reports:

Engine Built-in reports
Cucumber 3
Freshen 2
JBehave 2
NBehave 2
SpecFlow 2
Behat 3

Input data sources support:

Engine External Data Inclusions
Cucumber 0 0
Freshen 2 3
JBehave 3 2
NBehave 0 0
SpecFlow 0 0
Behat 0 0

Conclusion:

Table


Source
http://mkolisnyk.blogspot.co.uk/2012/06/gherkin-bdd-engines-comparison.html

Sublime and BDD

A simple guide about how to write formatted BDD features in Sublime. – Download what you want in Package Control. If you don’t have the package control in your sublime, follow these steps: – Open the console:

ctrl ` shortcut

– If your sublime is 2:

import urllib2,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')

– If your sublime is 3:

import urllib.request,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

– Hit Enter and restart the sublime after downloaded the package.

  How to install Packages from Package Control ?

– ‘Command+Shift+P’ – Type ‘Install Package’ and enter

– Choose the package as :

Cucumber

Gherkin[Cucumber] Formatter

Behat

Behat Snippets

How to use ?

You can try any of these commands to generate respective file.

– ‘Command+Shift+P’ – Type: ‘Gherkin’

– ‘Command+Shift+P’ – Type: ‘Feature’

– ‘Command+Shift+P’ – Type: ‘Scenario’ or ‘Scenario Outline’

– ‘Command+Shift+P’ – Type: ‘Example’

  If you want some snippet of Given/When/Then/etc, you can use the command  ‘Command+Shift+P’ – Type: ‘Given’

Screen Shot 2015-04-01 at 21.46.24

Easy and very useful, for this reason I like Sublime ! lol Thank you guys 🙂

Sourceshttp://shashikantjagtap.net/speed-up-your-bdd-with-sublime-text-2/ https://packagecontrol.io/installation

BDD – Summarized in 13 questions/tips and 1 example

Hi guys, today I will post a summary of a meet up that I went about BDD. It was very interesting and more clear than the others texts/posts that I found about.

1 –  Communication with all teams (business, developers, tests since beginning) is the key – Everyone should participate.

2 – What is the value of the scenario ?

3 – Could you write in another way/different steps ?

4 – Could you use the same steps ?

5 – Could you join some steps in other scenario to spend less time when you run the feature ?

6 – Your flow is decreasing the possible points of misunderstood gaps ?

7 – Are you doing the scenarios with participation of everyone in the beginning of the project ? When everyone is understanding the same thing and you starts to worry about tests in the beginning of the project, you spend less time/money than write test cases after development. Pay attention in your flow.

8 – Be curious ! Ask !

9 – Everything should be automated ? Remember that the effort spent when you automate something can be less valuable than manual testing.

10 – How many steps are you using in the scenarios, try don’t use more than 4 or 5. Make it simple.

11 – Use page object model – Better structure

12 – Be clear and objective when write the steps

13 – The feature is your documentation for end users, testers, developers. Following one of the Scrum rules, you don’t need more than this in your documentation process. Less time spent, more clear than huge documents (Because it uses examples), keeps the documentation together with the test.

14 – Use 4 layers – Example :

bdd

Thanks John F. Smart !

15 Expert Tips for Using Cucumber

Hey guys, I found these excellent tips to who are working with Cucumber and Calabash. Try follow each one to get more performance and use the best practices always 🙂

1. Feature Files Should Actually be Features, Not Entire Portions of an App

One feature per well named file, please, and keep the features focused.

2. Avoid Inconsistencies with Domain Language

You’ll get the most benefit out of using Cucumber when your customers are involved. To that end, make sure you use their domain language when you write stories. The best course of action is to have them involved in writing the stories.

3. Organize Your Features and Scenarios with the Same Thought You Give to Organizing Your Code

One useful way to organize things is by how fast they run. Use 2-3 levels of granularity for this:

  • Fast: scenarios that run very fast, e.g. under 1/10 of a second
  • Slow: scenarios that are slower but not painfully so, maybe under one second each
  • Glacial: scenarios that take a really long time to run

You can do this separation several different ways (and even some combination):

  • Put them in separate features
  • Put them in separate subdirectories
  • Tag them

4. Use Tags

Tags are a great way to organize your features and scenarios in non functional ways. You could use @small, @medium and @large, or maybe @hare, @tortoise, and @sloth. Using tags let you keep a feature’s scenarios together structurally, but run them separately. It also makes it easy to move features/scenarios between groups, and to have a given feature’s scenarios split between groups.

The advantage of separating them this way is that you can selectively run scenarios at different times and/or frequencies, i.e. run faster scenarios more often, or run really big/slow scenarios overnight on a schedule.

Tagging has uses beyond separating scenarios into groups based on how fast they are:

  • When they should be run: on @checkin, @hourly, @daily
  • What external dependencies they have: @local, @database, @network
  • Level: @functional, @system, @smoke
  • Etc.

5. Use Rake Tasks to Run Features

This provides a consistent environment for running features: this way each run uses the same set of options and parameters. This goes a long way toward maintaining deterministic results.

Another benefit is that this makes for easy integration with continuous integration tools. There is a single point of entry into the spec run, with all options/parameters encapsulated.

6. Don’t Get Carried Away with Backgrounds (Stick to Givens)

The larger the background, the greater the load of understanding for each scenario. Scenarios that contain all the details are self-contained and as such, can be more understandable at a glance.

7. Make Scenarios Independent and Deterministic

There shouldn’t be any sort of coupling between scenarios. The main source of such coupling is state that persists between scenarios. This can be accidental, or worse, by design. For example one scenario could step through adding a record to a database, and subsequent scenarios depend on the existence of that record.

This may work, but will create a problem if the order in which scenarios run changes, or they are run in parallel. Scenarios need to be completely independent.

Each time a scenario runs, it should run the same, giving identical results. The purpose of a scenario is to describe how your system works. If you don’t have confidence that this is always the case, then it isn’t doing its job. If you have non-deterministic scenarios, find out why and fix them.

8. Write Scenarios for the Non-Happy-Path Cases As Well

Happy path tests are easy; edge cases and failure scenarios take more thought and work. Here’s where having some good (and yet pathological) testers on the team can reap rewards.

Use rcov with your full Cucumber runs to find holes in coverage.

9. Be DRY: Refactor and Reuse Step Definitions

Especially look for the opportunity to make reusable step definitions that are not feature specific. As a project proceeds, you should be accumulating a library of step definitions. Ideally, you will end up with step definitions that can be used across projects.

10. Use a Library (Such as Chronic) for Parsing Time in Your Step Definitions

This allows you to use time in scenarios in a natural way. This is especially useful for relative times.

Background:
  Given a user signs up for a 30 day account

Scenario: access before expiry
  When they login in 29 days
  Then they will be let in

Scenario: access after expiry
  When they login in 31 days
  Then they will be asked to renew

11. Revisit, Refactor, and Improve Your Scenarios and Steps

Look for opportunities to generalize your steps and reuse them. You want to accumulate a reusable library of steps so that writing additional features takes less and less effort over time.

12. Refactor Language and Steps to Reflect Better Understanding of Domain

This is an extension of the previous point; as your understanding of the domain and your customer’s language/terminology improves, update the language used in your scenarios.

13. Use Compound Steps to Build Up Your Language

Compound steps (calling steps from steps) can help make your features more concise while still keeping your steps general—just don’t get too carried away. For example:

Given /^the user (.*) exists$/ do |name|
  # ...
end

Given /^I log in as (.*)$/ do |name|
  # ...
end

Given /^(.*) is logged in$/ do |name|
  Given "the user #{name} exists"
  Given "I log in as #{name}"
end

14. Use Parallel Step Definitions to Support Different Implementations for Features

For example, running features against Webrat and Selenium. Put these step definitions somewhere where they won’t be auto-loaded, and require them from the command line or rake task.

15. Avoid Using Conjunctive Steps

Each step should do one thing. You should not generally have step patterns containing “and.” For example:

Given A and B

should be split into two steps:

Given A
And B

 

Bye 🙂

Font: https://blog.engineyard.com/2009/15-expert-tips-for-using-cucumber/

Summary of Calabash iOS Ruby API – Assertions

Hi guys ! I hope you are well ! Here there are many commands of calabash-ios that are very useful 🙂

Assertions

 

fail(msg="Error. Check log for details.")

check_element_exists(query)
check_element_does_not_exist(query)
check_view_with_mark_exists(expected_mark)

check_element_exists("view marked:'#{expected_mark}'")

 

Touch

 

touch(uiquery, options={})

 

irb(main):037:0> touch("view marked:'switch'")
irb(main):038:0> tap 'switch'
irb(main):040:0> touch("view marked:'First'", :offset => {:x => 50, :y => 0})
irb(main):041:0> touch(nil, :offset => {:x => 50, :y => 0})

 

Keyboard

 

keyboard_enter_char(chr)

irb(main):043:0> keyboard_enter_char "a"
irb(main):076:0> keyboard_enter_char "More"

keyboard_enter_text(text)

irb(main):044:0> keyboard_enter_text "The Quick Brown Fox"

done

Scroll

scroll(uiquery, direction)

irb(main):082:0> scroll "scrollView", :down

 

Tables

 

scroll_to_row(uiquery, number)

irb(main):081:0> scroll_to_row "tableView", 2

scroll_to_cell(options)

{:query => "tableView",
 :row => 0,
 :section => 0,
 :scroll_position => :top,
 :animate => true}
irb(main):003:0> scroll_to_cell(:row => 13, :section => 0)
=> ["; contentOffset: {0, 0}>. Delegate: LPThirdViewController, DataSource: LPThirdViewController"]

:row the row to scroll to
:section the section to scroll to
:scroll_position the position to scroll to :top, :bottom, :middle
:animate animate the scrolling or not

each_cell(options, &block)

{:query => "tableView", #the table view to act on
 :post_scroll => 0.3,  #a pause after each action taken
 :skip_if => nil, #an optional proc to skip some cells
 :animate => true #animate the scrolling?
}
irb(main):008:0> each_cell(:post_scroll=>0) do |row, sec|
irb(main):009:1* puts "Row #{row} in Section #{sec}"
irb(main):010:1> end
Row 0 in Section 0
Row 1 in Section 0
Row 2 in Section 0
Row 3 in Section 0
...
irb(main):001:0> table_labels = []
=> []

irb(main):002:0> each_cell(:animate => false, :post_scroll => 0.1) do |row, sec|
irb(main):003:1*  txt = query("tableViewCell indexPath:#{row},#{sec} label", :text).first
irb(main):004:1>  table_labels << txt irb(main):005:1> end
=> 1

irb(main):006:0> table_labels
=> ["Cell 0", "Cell 1", "Cell 2", "Cell 3", "Cell 4", "Cell 5", "Cell 6", "Cell 7", "Cell 8", "Cell 9", "Cell 10", "Cell 11", "Cell 12", "Cell 13", "Cell 14", "Cell 15", "Cell 16", "Cell 17", "Cell 18", "Cell 19", "Cell 20", "Cell 21", "Cell 22", "Cell 23", "Cell 24", "Cell 25", "Cell 26", "Cell 27", "Cell 28", "Cell 29"]

 

Rotation

rotate(dir)

irb(main):083:0> rotate :left

 

(Event) Playback

playback(recording, options={})

irb(main):103:0> playback "drag_switch_around", :query => "view marked:'switch'", :offset => {:x=>2, :y=>0}

record_begin and record_end

irb(main):104:0> record_begin
=> ""
irb(main):105:0> record_end "move_down"
=> "move_down_ios5_iphone.base64"

 

Location

set_location(options)

:place => "Tower of London"
:latitude => ..., :longitude => ...

 

Backdoor

backdoor(sel, arg)

- (NSString *) calabashBackdoor:(NSString *)aIgnorable;
irb(main):002:0> backdoor("calabashBackdoor:", "")
=> "YES"

 

Screenshot

screenshot(options={:prefix=>nil, :name=>nil})

screenshot({:prefix => "/Users/krukow/tmp", :name=>"my.png"})

screenshot_embed(options={:prefix=>nil, :name=>nil, :label => nil})

screenshot_embed({:prefix => "/Users/krukow/tmp", :name=>"my.png", :label => "Mine"})

 

Misc

 

server_version

irb(main):026:0> server_version
=> {"outcome"=>"SUCCESS", "app_name"=>"LPSimpleExample-cal", "simulator_device"=>"iPhone", "iOS_version"=>"5.1", "app_version"=>"1.0", "system"=>"x86_64", "app_id"=>"com.lesspainful.example.LPSimpleExample-cal", "version"=>"0.9.126", "simulator"=>"iPhone Simulator 358.4, iPhone OS 5.1 (iPhone/9B176)"}

 

client_version

irb(main):027:0> client_version
=> "0.9.127.pre1"

 

calabash_exit

irb(main):028:0> calabash_exit
=> []
irb(main):029:0> server_version
Errno::ECONNREFUSED: Connection refused - connect(2) (http://localhost:37265)

 

escape_quotes(str)

irb(main):007:0> quoted = escape_quotes("Karl's child")
=> "Karl\\'s child"
irb(main):008:0> query("view marked:'#{quoted}'")

 

macro(txt)

macro 'I touch "Second"'

lbl = ".......a long text......"
macro %Q[I use a step with "double" quotes and 'single' and #{lbl}]

 

flash(uiquery)

flash("TableView index:2")

 

Font: https://github.com/calabash/calabash-ios/wiki/03.5-Calabash-iOS-Ruby-API