drupal.org/u/gedur
Module maintainer: Ga Push, Commerce Google Analytics, IP, Misery...
In this session we will talk about:
Software development process that emerged from test-driven development (TDD).
An idea about how software development should be managed by both business interests and technical insight.
It combines the general techniques and principles of TDD with ideas from domain-driven design and object-oriented analysis and design to provide software development and management teams with shared tools and a shared process to collaborate on software development.
Clients and users have needs
and they want systems to satisfy them
The functionality of an application
is a set of all system features
The sum of features makes the project
Ensure components quality, check specifications, avoid regressions...
After Development vs Before Development
Testing at the end of the project
Testing at the end of each sprint
Testing at the beginning of each sprint
Test Driven Development (TDD)
Components of a software are tested, ...each unit of the software performs as designed.
A unit is the smallest testable part of software.
class StackTest extends TestCase {
public function testPushAndPop()
{
$stack = [];
$this->assertEquals(0, count($stack));
array_push($stack, 'foo');
$this->assertEquals('foo', $stack[count($stack)-1]);
$this->assertEquals(1, count($stack));
$this->assertEquals('foo', array_pop($stack));
$this->assertEquals(0, count($stack));
}
}
Individual software modules are combined and tested as a group.
After unit testing.
Test the features/functionality of the system or Software, should cover all the scenarios including failure paths and boundary cases.
class Breadcrumb404Test extends BrowserTestBase {
...
public function testBreadcrumbOn404Pages() {
...
$this->drupalGet('/not-found-2');
$next_count = count($this->getBreadcrumbCacheEntries());
$this->assertEquals($base_count, $next_count);
$this->drupalGet('/not-found-3');
$next_count = count($this->getBreadcrumbCacheEntries());
$this->assertEquals($base_count, $next_count);
}
...
}
Wait!!!
I just use components tested by unit tests, It's enough!!!
If all the pieces runs ok, then the site will run ok.
...view more in reddit.com/r/ProgrammerHumor/search?q=unit
All unit, integration,... tests passed but,
Have we created the right product?
Have we also failed?
Determine whether they meet the specified requirements. | Determine whether it satisfies specified business requirements. |
Are we building the product right? |
Are we building the right product? |
Project specifications/requirements
System perspective, just characteristics, no user interaction
User workflow perspective, mockups, user interaction, edge use cases
User centered design
User perspective, focused on user value
As a { who }
I want to { what }
so that { why }
As an anonymous I want to register into the site so that I can access to the private section
As an editor I want to create articles so that the site will have new content
As an editor I want to edit articles so that I can update them and fix mistakes
As a manager I want to cancel user accounts so that I can keep the accounts under control
As a sales manager I want to download sales reports in csv so that I can work with them later
Describe concrete interactions for each User Story. Acceptance criteria.
As an anonymous I want to register into the site so that I can access to the private section
Preconditions | Given I am an anonymous user |
Actions |
When I go to user register I should see the fields: name, surname, email and password I fill name with "TestName" ... I press "Create account" |
Postconditions | An account for "TestName" has been created |
Along with the case, alternative paths may show up
As an anonymous I want to register into the site so that I can access to the private section
...
4. I select "individual" as user type
5. I fill user name with "Peter"
...
A individual account for "Peter" has been created
4.A. I select "company" as user type
5.A. I fill company name with "Drupal"
...
A company account for "Drupal" has been created
Alternative steps can finalize in error steps
Sunny Day: use case without errors
4. I select "individual" as user type
5. I fill user name with "Peter"
6. I fill mail with "FAKE@@MAIL..cc"
...
10. And I press "Create Account"
Then I should see "email field is not valid"
Writing use cases can be boring, use strategies to optimize (without losing readability).
Story: As a store owner
I want to add items back to stock when they're returned
so that I can keep track of stock
Scenario 1: Refunded items should be returned to stock
Given that a customer previously bought a black sweater from me
And I have three black sweaters in stock.
When he returns the black sweater for a refund
Then I should have four black sweaters in stock.
Scenario 2: Replaced items should be returned to stock
Given that a customer previously bought a blue garment from me
And I have two blue garments in stock
And three black garments in stock.
When he returns the blue garment for a replacement in black
Then I should have three blue garments in stock
And two black garments in stock.
Gherkin language syntax example. The term Gherkin, however, is specific to the Cucumber, JBehave and Behat software tools.
Behat is an open source Behaviour-Driven Development framework for PHP. It is a tool to support you in delivering software that matters through continuous communication, deliberate discovery and test-automation.
# Create the directory:
$ mkdir /opt/behat && cd /opt/behat
# Install with composer:
$ composer require drupal/drupal-extension
# Symbolic link to $PATH
$ ln -s /opt/behat/vendor/bin/behat /usr/local/bin/behat
# Check version:
$ behat --version
installation for Drupal projects
config | behat.yml |
Contexts | /bootstrap (folder) |
Features | /features (folder) |
Detailed installation and configuration see this post
Drupal
└─ sites/
├─ all/
│ └─ test/
│ └─ behat/
│ ├─ features/
│ │ ├─ anonymous.access.feature ← User Stories
│ │ └─ *.feature
│ │
│ └─ bootstrap/
│ ├─ FeatureContext.php ← Base Context
│ └─ ... ← Other Contexts
└─ default/
└─ behat.yml ← Conf yml
# Go to drupal docroot:
$ cd /var/vhost/mysproject/docroot
# Execute behat:
$ behat --config sites/default/behat.yml --tags="register"
Execution for Drupal project
@check @anonymous @statistics
Scenario: Check, Statistics and Statistics menu # /vagrant/vhosts/project/docroot/sites/all/tests/behat/features/project/user_anonymous.feature:71
Given I am an anonymous user # FeatureContext::assertAnonymousUser()
And I go to "/" # Drupal\DrupalExtension\Context\MinkContext::visit()
When I click "Statistics" in the "main menu" # Drupal\DrupalExtension\Context\MinkContext::assertRegionLinkFollow()
Then the url should match "/statistics" # Drupal\DrupalExtension\Context\MinkContext::assertUrlRegExp()
And I should see "Statistics" in the "statistics menu pane full" # Drupal\DrupalExtension\Context\MinkContext::assertRegionText()
And I should see the link "World Cup Ranking" in the "panel column last" # Drupal\DrupalExtension\Context\MinkContext::assertLinkRegion()
And I should see the link "World Ranking" in the "panel column last" # Drupal\DrupalExtension\Context\MinkContext::assertLinkRegion()
And I should see the link "World Records" in the "panel column last" # Drupal\DrupalExtension\Context\MinkContext::assertLinkRegion()
And I should see the link "Longines Prize for Precision" in the "panel column last" # Drupal\DrupalExtension\Context\MinkContext::assertLinkRegion()
When I click "World Cup Ranking" in the "panel column last" # Drupal\DrupalExtension\Context\MinkContext::assertRegionLinkFollow(
...
Example of execution steps
48 scenarios (48 passed)
773 steps (773 passed)
--- Failed scenarios:
../features/authenticated.donation_create.feature:17
../features/editor.news_edit.feature:9
21 scenarios (19 passed, 2 failed)
289 steps (274 passed, 2 failed, 13 skipped)
As an anonymous
I want to register into the site
so that I can join the program
As an anonymous
I want to pull data from Linkedin while I'm registering into the site
so that I can do it easier
As an anonymous I want to register into the site so that I can join the program
Feature: As an anonymous
I want to register into the site
so that I can join the program
@TODO: Scenario SunnyDay
@TODO: Scenario Alternative 1..N
@TODO: Scenario Errors 1..N
As an anonymous I want to register into the site so that I can join the program
@anonymous @user-register @sunnyday
Scenario: Fills all fields
and joins the program as invididual
# Preconditions:
Given I am an anonymous user
And I go to "/user/register"
# Actions:
Then I should see "Type"
And I should see "Name"
And I should see "Surname"
And I should see "Why do you want to join the program?"
And I should see "I accept the terms & conditions"
Then I select "individual" from "Type"
Then I fill "Name" with "TestName"
And I fill "Surname" with "TestSurname"
And I fill "Why do you want to join the program?" with "Some text..."
And I press "I accept the terms & conditions"
When I click "Create Account"
Then I should see "Welcome to the program!"
# Posconditions:
Then an individual account has been created for "TestName"
...
As an anonymous I want to register into the site so that I can join the program
@anonymous @user-register @variant
Scenario: Fills all fields
and joins the program as company
# Preconditions:
Given I am an anonymous user
And I go to "/user/register"
# Actions:
Then I select "company" from "Type"
And I should not see "Surname"
And I fill "Name" with "TestName"
And I fill "Why do you want to join the program?" with "Some text..."
And I press "I accept the terms & conditions"
When I click "Create Account"
Then I should see "Welcome to the program!"
# Posconditions:
Then a company account has been created for "TestName"
...
As an anonymous I want to register into the site so that I can join the program
@anonymous @user-register @error
Scenario: Fails filling fields
# Preconditions:
Given I am an anonymous user
And I go to "/user/register"
# Actions:
When I click "Create Account"
Then I should see the message
"The field name is required"
And I should see the message
"The field surname is required"
And I should see the message
"The field Why do you want to join the program? is required"
And I should see the message
"The field I accept the terms & conditions is required"
Then I fill "Why do you want to join the program?"
with "Some short text..."
When I click "Create Account"
Then I should see the message "The field Why do you want to join the program?
should have 300 characters at least"
...
As an anonymous I want to pull data from Linkedin while I'm registering into the site so that I can do it easier
Feature: As an anonymous
I want to pull data from Linkedin while I'm registering into the site
so that I can do it easier
@TODO: Scenario SunnyDay
@TODO: Scenario Alternative 1..N
@TODO: Scenario Errors 1..N
As an anonymous I want to pull data from Linkedin while I'm registering into the site so that I can do it easier
@anonymous @user-register @Linkedin @sunnyday
Scenario: Fills all fields with Linkedin data
and joins the program as invididual
# Preconditions:
Given I am an anonymous user
And I go to "/user/register"
And I have a Linkedin account
# Actions:
When I click "Pull data from Linkedin"
And I login in Linkedin and give permissions
Then I should see the field "Name"
filled with "LinkedinTestName"
And I should see the field "Surname"
filled with "LinkedinTestSurName"
Then I select "individual" from "Type"
And I fill "Why do you want to join the program?"
with "Some text..."
And I press "I accept the terms & conditions"
When I click "Create Account"
Then I should see "Welcome to the program!"
# Posconditions:
Then an individual account has been created
for "LinkedinTestName"
...
As an anonymous I want to pull data from Linkedin while I'm registering into the site so that I can do it easier
Company? Incomplete profile?
As an anonymous I want to pull data from Linkedin while I'm registering into the site so that I can do it easier
No Linkedin loggin? No privileges granted?
Easy?
Willing to write your own BDD tests?
Given I am an attendee
And I am brave enough to ask a question
When I ask for the microphone
And I ask a question to the speaker
Then I get an answer [ maybe a good one :) ]