Difference between revisions of "Exploring your first cucumber project"

From Test Automation Wiki
Jump to: navigation, search
(Created page with "<div style="display: block; float:right; background-color: #FDFDFD; border: 1px #AFAFAF solid; padding: 10px;"> <categorytree mode=all depth=1>Web_Test_Automation_Tutorial</ca...")
 
(7 intermediate revisions by 3 users not shown)
Line 7: Line 7:
 
<h2>Feature files</h2>
 
<h2>Feature files</h2>
 
<p>
 
<p>
Let's start off by having a look at the feature files: <code>./features/example.feature</code>. You should see the following:
+
Let's start off by having a look at the feature files. Open <code>./features/1_basic.feature</code> and you should see the following:
 
<ul>
 
<ul>
<li>Tags <code>@emaple</code></li>
+
<li>Tags <code>@example</code></li>
<li>a Feature <code>Feature: Example Feature</code>
+
<li>a Feature <code>Feature: Basic Feature</code>
 
<li>A description of the feature <code>When I want (...) the tests below</code>
 
<li>A description of the feature <code>When I want (...) the tests below</code>
 
<li>Multiple sceanrios <code>Scenario: example01 - Spritecloud search</code>
 
<li>Multiple sceanrios <code>Scenario: example01 - Spritecloud search</code>
Line 17: Line 17:
 
</p>
 
</p>
  
<h3>Tags</h2>
+
<h3>Tags</h3>
<p>A tag is used to be able to filter certain feature or scenario's when running your script in Cucumber. Try it out:</p>
+
<p>A tag is used to be able to filter certain feature or scenario's when running your script in Cucumber. Open 'CMD', go to your project folder and try it out:</p>
 
<source>
 
<source>
   bundle exec cucumber -t @example
+
   bundle exec cucumber -t @basic
   # Will run the complete Feature: Example
+
   # Will run the complete Feature: Example Feature
   bundle exec cucumber -t @example01
+
   bundle exec cucumber -t @basic_01
 
   # Will only run the first Scenario
 
   # Will only run the first Scenario
   bundle exec cucumber -t @example -t ~@example01
+
   bundle exec cucumber -t @basic -t ~@basic_01
 
   # Will run all scenario's in the Example feature, except for the first one.
 
   # Will run all scenario's in the Example feature, except for the first one.
 
</source>
 
</source>
  
<h3>Feature, Scenario, Steps</h2>
+
<h3>Feature, Scenario, Steps</h3>
<p>A feature represents a major functionality of a website. This could be a single page or a functionality over multiple pages. Weather something actually is a separate feature is left to your own judgement. You don't want too much scenario's in 1 feature file, but also, you don't want too little. For example:</p>
+
<h4>Features</h4>
<h4>A product detail page</h4>
+
<p>A feature represents a major functionality of a website. This could be a single page or a functionality over multiple pages. Whether something actually is a separate feature is left to your own judgement. You don't want too much scenario's in 1 feature file, but also, you don't want too little. For example:</p>
 +
<h5>A product detail page</h5>
 
<p>This could be a feature on itself with all the functionalities this page could have. Think of:
 
<p>This could be a feature on itself with all the functionalities this page could have. Think of:
 
* Viewing the product image
 
* Viewing the product image
Line 36: Line 37:
 
* Folding open a detailed description of the product.
 
* Folding open a detailed description of the product.
 
</p>
 
</p>
<h4>Ordering a product</h4>
+
<h5>Ordering a product</h5>
 
<p>This is not a separate page, but more a flow that a user goes trough. Even though a part of this Feature is the product detail page, the complete flow of ordering a product goes trough multiple functionalities. In the end, on a feature like this, you would want to test specific order types, for example:  
 
<p>This is not a separate page, but more a flow that a user goes trough. Even though a part of this Feature is the product detail page, the complete flow of ordering a product goes trough multiple functionalities. In the end, on a feature like this, you would want to test specific order types, for example:  
 
* Ordering 1 product with shipping cost
 
* Ordering 1 product with shipping cost
Line 42: Line 43:
 
* Ordering a product with a discount code
 
* Ordering a product with a discount code
 
</p>
 
</p>
<p>In a scenario, you will confirm 1 functionality. An often made mistake is to confirm multiple functionalities in 1 scenario. On large projects, this will ruin the maintainability of your test automation suite. In <code>example.feature</code> you will see that every scenario just confirms 1 thing.</p>
+
<h4>Scenario's</h4>
<p>A step is the part that will actually execute your code.
+
<p>In a scenario, you will confirm 1 functionality. An often made mistake is to confirm multiple functionalities in 1 scenario. On large projects, this will ruin the maintainability of your test automation suite. In <code>1_basic.feature</code> you will see that every scenario just confirms 1 thing.</p>
 +
<h4>Steps</h4>
 +
<p>A step is the part that will actually execute your Selenium code. More about this in the next heading: Step Definitions</p>
  
 +
<h2>Step definitions</h2>
 +
<h3>Organising your files</h3>
 +
<p>If you go to the folder <code>./features/step_definitions/</code> You will see 3 files:
 +
* <code>account_steps.rb</code> contains all the steps regarding "account" functions.
 +
* <code>basic_steps.rb</code> contains all the steps regarding "basic" functions.
 +
* <code>todo_steps.rb</code> contains all the steps regarding "todo" functions.
 +
This is an example of how you can manage your step definitions orderly. In the end, just like features, it's to the TA engineer how they feel is the most organised way. For example, you can create a new file for every feature, or you could even write everything into 1 big step definition file (not recommended).
 +
</p>
 +
<h3>The step definition</h3>
 +
<p>Open <code>./features/step_definitions/basic_steps.rb</code> and have a look at line number 33-42: "the user clicks on link ..."</p>
 +
<source>
 +
When(/^the user clicks on link "(.*?)"$/) do |url|
 +
  # Search for the element that includes the expected text
 +
  browser.wait(
 +
    :like => {
 +
      :element => :a,
 +
      :attribute => :href,
 +
      :include => url
 +
    }
 +
  ).click
 +
end
 +
</source>
 +
<p>Find out more about how to define a step on [https://docs.cucumber.io/cucumber/step-definitions/ Cucumber Step definitions]. In this case a wildcard is used in the step definition <code>(.*?)</code>. This wildcard is then stored in a variable <code>url</code>.</p>
 +
<p>Then bewteen "When" and "end", there is code that will interact with the browser. What it's basically saying is 'Look for an element <code><a href="url"></code> where <code>url</code> is whatever was filled into the step. More about interacting with the browser in the next chapter of this tutorial.</p>
  
 +
<h3>config.yml</h3>
 +
<p>The file <code>./config/config.yml</code> is used to re-used defined variables. Mostly used to store user credentials or to translate a page name into a page URL. Also commonly used to define different data between different test environments. For example, the URL to the test environment is different than the one to the production environment.</p>
 +
<p>Lapis Lazuli has build in functions that loads these variables:
 +
* <code>env('pages.root')</code> will load the root configuration value from the selected environment, E.G. production -> pages -> root = https://spritecloud.com
 +
* <code>config('user.default-user.username'</code> will load a configuration value independent from the selected environment, so users -> default-user -> username = test
 +
</p>
 +
<h3>Other advanced files</h3>
 +
<h4>env.rb</h4>
 +
<p>When running cucumber in the console, <code>./features/support/env.rb</code> is the first file that is loaded. It will start Lapis Lazuli and load all the dependent gems. Also, in this file you can add repeating scripts, that should be ran before or after everything feature, scenario or step. See [https://docs.cucumber.io/cucumber/api/#hooks Cucumber Hooks] for more information.</p>
  
 +
<h4>functions.rb</h4>
 +
<p>In this file we've defined multiple repeating functions. It's created this way to prevent too much code in the step_definitions. Also, you don't want to repeat yourself. In the folder <code>./features/support/</code> you can add any <code>.rb</code> file and it will be loaded before your cucumber feature files are executed.</p>
  
 +
<h4>Gemfile</h4>
 +
<p>Finally, there is the Gemfile, here you can add any Gems that you're using for your project. For example, sometimes you want to directly connect to a SOAP back-end environment, for this there is a Gem. Simply add the gem to your Gemfile and you can start using the Gems functionalities in your step definitions.</p>
  
 
[[Category:Web Test Automation Tutorial|4]]
 
[[Category:Web Test Automation Tutorial|4]]

Revision as of 14:54, 5 September 2018

This is more of an informative part of the tutorial. If you don't feel like reading, you can skip to part 5: Exercises

Feature files

Let's start off by having a look at the feature files. Open ./features/1_basic.feature and you should see the following:

  • Tags @example
  • a Feature Feature: Basic Feature
  • A description of the feature When I want (...) the tests below
  • Multiple sceanrios Scenario: example01 - Spritecloud search
  • Steps Given the user navigates to "blog"

Tags

A tag is used to be able to filter certain feature or scenario's when running your script in Cucumber. Open 'CMD', go to your project folder and try it out:

  bundle exec cucumber -t @basic
  # Will run the complete Feature: Example Feature
  bundle exec cucumber -t @basic_01
  # Will only run the first Scenario
  bundle exec cucumber -t @basic -t ~@basic_01
  # Will run all scenario's in the Example feature, except for the first one.

Feature, Scenario, Steps

Features

A feature represents a major functionality of a website. This could be a single page or a functionality over multiple pages. Whether something actually is a separate feature is left to your own judgement. You don't want too much scenario's in 1 feature file, but also, you don't want too little. For example:

A product detail page

This could be a feature on itself with all the functionalities this page could have. Think of:

  • Viewing the product image
  • Adding an item to your basket
  • Folding open a detailed description of the product.

Ordering a product

This is not a separate page, but more a flow that a user goes trough. Even though a part of this Feature is the product detail page, the complete flow of ordering a product goes trough multiple functionalities. In the end, on a feature like this, you would want to test specific order types, for example:

  • Ordering 1 product with shipping cost
  • Ordering multiple products, going over the free shipping threshold
  • Ordering a product with a discount code

Scenario's

In a scenario, you will confirm 1 functionality. An often made mistake is to confirm multiple functionalities in 1 scenario. On large projects, this will ruin the maintainability of your test automation suite. In 1_basic.feature you will see that every scenario just confirms 1 thing.

Steps

A step is the part that will actually execute your Selenium code. More about this in the next heading: Step Definitions

Step definitions

Organising your files

If you go to the folder ./features/step_definitions/ You will see 3 files:

  • account_steps.rb contains all the steps regarding "account" functions.
  • basic_steps.rb contains all the steps regarding "basic" functions.
  • todo_steps.rb contains all the steps regarding "todo" functions.

This is an example of how you can manage your step definitions orderly. In the end, just like features, it's to the TA engineer how they feel is the most organised way. For example, you can create a new file for every feature, or you could even write everything into 1 big step definition file (not recommended).

The step definition

Open ./features/step_definitions/basic_steps.rb and have a look at line number 33-42: "the user clicks on link ..."

When(/^the user clicks on link "(.*?)"$/) do |url|
  # Search for the element that includes the expected text
  browser.wait(
    :like => {
      :element => :a,
      :attribute => :href,
      :include => url
    }
  ).click
end

Find out more about how to define a step on Cucumber Step definitions. In this case a wildcard is used in the step definition (.*?). This wildcard is then stored in a variable url.

Then bewteen "When" and "end", there is code that will interact with the browser. What it's basically saying is 'Look for an element <a href="url"> where url is whatever was filled into the step. More about interacting with the browser in the next chapter of this tutorial.

config.yml

The file ./config/config.yml is used to re-used defined variables. Mostly used to store user credentials or to translate a page name into a page URL. Also commonly used to define different data between different test environments. For example, the URL to the test environment is different than the one to the production environment.

Lapis Lazuli has build in functions that loads these variables:

  • env('pages.root') will load the root configuration value from the selected environment, E.G. production -> pages -> root = https://spritecloud.com
  • config('user.default-user.username' will load a configuration value independent from the selected environment, so users -> default-user -> username = test

Other advanced files

env.rb

When running cucumber in the console, ./features/support/env.rb is the first file that is loaded. It will start Lapis Lazuli and load all the dependent gems. Also, in this file you can add repeating scripts, that should be ran before or after everything feature, scenario or step. See Cucumber Hooks for more information.

functions.rb

In this file we've defined multiple repeating functions. It's created this way to prevent too much code in the step_definitions. Also, you don't want to repeat yourself. In the folder ./features/support/ you can add any .rb file and it will be loaded before your cucumber feature files are executed.

Gemfile

Finally, there is the Gemfile, here you can add any Gems that you're using for your project. For example, sometimes you want to directly connect to a SOAP back-end environment, for this there is a Gem. Simply add the gem to your Gemfile and you can start using the Gems functionalities in your step definitions.