Add SeleniumBase Behave-BDD examples

This commit is contained in:
Michael Mintz 2022-05-13 16:05:06 -04:00
parent 2c45c8f682
commit 1041387475
15 changed files with 758 additions and 0 deletions

239
examples/behave_bdd/ReadMe.md Executable file
View File

@ -0,0 +1,239 @@
<h2><img src="https://seleniumbase.io/img/logo6.png" title="SeleniumBase" width="32" /> 🐝 Behave test runner for SeleniumBase 🐝</h2>
🐝 (Utilizes the [Behave BDD Python library](https://github.com/behave/behave). For more info, see the [Behave tutorial](https://behave.readthedocs.io/en/stable/tutorial.html) and read about [Behave's Gherkin model](https://behave.readthedocs.io/en/stable/gherkin.html).)
🐝 Behave examples with SeleniumBase: [SeleniumBase/examples/behave_bdd](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/behave_bdd)
```bash
> cd examples/behave_bdd/
> behave features/realworld.feature -T -D dashboard -k
Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html
********************************************************************************
Feature: SeleniumBase scenarios for the RealWorld App # features/realworld.feature:1
Scenario: Verify RealWorld App (log in / sign out) # features/realworld.feature:3
Given Open "seleniumbase.io/realworld/login" # ../../sbase/steps.py:4
And Clear Session Storage # ../../sbase/steps.py:374
When Type "demo_user" into "#username" # ../../sbase/steps.py:22
And Type "secret_pass" into "#password" # ../../sbase/steps.py:22
And Do MFA "GAXG2MTEOR3DMMDG" into "#totpcode" # ../../sbase/steps.py:179
Then Assert exact text "Welcome!" in "h1" # ../../sbase/steps.py:75
And Highlight "img#image1" # ../../sbase/steps.py:82
And Click 'a:contains("This Page")' # ../../sbase/steps.py:13
And Save screenshot to logs # ../../sbase/steps.py:107
When Click link "Sign out" # ../../sbase/steps.py:91
Then Assert element 'a:contains("Sign in")' # ../../sbase/steps.py:52
And Assert text "You have been signed out!" # ../../sbase/steps.py:68
✅ Scenario Passed!
- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html
==================================================================================
1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 0 skipped
12 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m4.682s
```
🐝 Another example, which uses higher-level Behave steps to simplify the ``.feature`` file:
```bash
> cd examples/behave_bdd/
> behave features/calculator.feature:61 -T -D dashboard -k
Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html
********************************************************************************
Feature: SeleniumBase scenarios for the Calculator App # features/calculator.feature:1
Background: # features/calculator.feature:3
Scenario: 7.0 × (3 + 3) = 42 # features/calculator.feature:49
Given Open the Calculator App # features/steps/calculator.py:4
When Press C # features/steps/calculator.py:9
And Press 7 # features/steps/calculator.py:79
And Press . # features/steps/calculator.py:104
And Press 0 # features/steps/calculator.py:94
And Press × # features/steps/calculator.py:29
And Press ( # features/steps/calculator.py:14
And Press 3 # features/steps/calculator.py:59
And Press + # features/steps/calculator.py:39
And Press 3 # features/steps/calculator.py:59
And Press ) # features/steps/calculator.py:19
Then Verify output is "7.0×(3+3)" # features/steps/calculator.py:135
When Press = # features/steps/calculator.py:44
Then Verify output is "42" # features/steps/calculator.py:135
✅ Scenario Passed!
- Dashboard: /Users/michael/github/SeleniumBase/examples/behave_bdd/dashboard.html
==================================================================================
1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 8 skipped
14 steps passed, 0 failed, 60 skipped, 0 undefined
Took 0m1.672s
```
🔵🐝⚪ With the Dashboard enabled, you'll get one of these:
<img src="https://seleniumbase.io/cdn/img/sb_behave_dashboard.png" title="SeleniumBase" width="600">
### 🐝 Understanding Behave files:
🐝 The ``*.feature`` files can use any step seen from:
```bash
behave --steps-catalog
```
🐝 SeleniumBase includes several pre-made Behave steps, which you can use by creating a Python file with the following line in your ``features/steps/`` directory:
```python
from seleniumbase.behave import steps # noqa
```
🐝 Inside your ``features/environment.py`` file, you should have the following:
```python
from seleniumbase import BaseCase
from seleniumbase.behave import behave_sb
behave_sb.set_base_class(BaseCase) # Accepts a BaseCase subclass
from seleniumbase.behave.behave_sb import before_all # noqa
from seleniumbase.behave.behave_sb import before_feature # noqa
from seleniumbase.behave.behave_sb import before_scenario # noqa
from seleniumbase.behave.behave_sb import before_step # noqa
from seleniumbase.behave.behave_sb import after_step # noqa
from seleniumbase.behave.behave_sb import after_scenario # noqa
from seleniumbase.behave.behave_sb import after_feature # noqa
from seleniumbase.behave.behave_sb import after_all # noqa
```
🐝 If you've already created a subclass of ``BaseCase`` with custom methods, you can swap ``BaseCase`` in with your own subclass, which will allow you to easily use your own custom methods in your Behave step definitions.
🐝 Here's an example Python file in the ``features/steps/`` folder:
```python
from behave import step
@step("Open the Swag Labs Login Page")
def go_to_swag_labs(context):
sb = context.sb
sb.open("https://www.saucedemo.com")
sb.clear_local_storage()
@step("Login to Swag Labs with {user}")
def login_to_swag_labs(context, user):
sb = context.sb
sb.type("#user-name", user)
sb.type("#password", "secret_sauce\n")
@step("Verify that the current user is logged in")
def verify_logged_in(context):
sb = context.sb
sb.assert_element("#header_container")
sb.assert_element("#react-burger-menu-btn")
sb.assert_element("#shopping_cart_container")
@step('Add "{item}" to cart')
def add_item_to_cart(context, item):
sb = context.sb
sb.click('div.inventory_item:contains("%s") button[name*="add"]' % item)
```
🐝 A ``*.feature`` file could look like this:
```bash
Feature: SeleniumBase scenarios for the Swag Labs App
Background:
Given Open the Swag Labs Login Page
Scenario: User can order a backpack from the store
When Login to Swag Labs with standard_user
Then Verify that the current user is logged in
And Save price of "Backpack" to <item_price>
When Add "Backpack" to Cart
Then Verify shopping cart badge shows 1 item(s)
When Click on shopping cart icon
And Click Checkout
And Enter checkout info: First, Last, 12345
And Click Continue
Then Verify 1 "Backpack"(s) in cart
And Verify cost of "Backpack" is <item_price>
And Verify item total is $29.99
And Verify tax amount is $2.40
And Verify total cost is $32.39
When Click Finish
Then Verify order complete
When Logout from Swag Labs
Then Verify on Login page
```
🐝 Here's another example of a ``*.feature`` file:
```bash
Feature: SeleniumBase scenarios for the RealWorld App
Scenario: Verify RealWorld App (log in / sign out)
Given Open "seleniumbase.io/realworld/login"
And Clear Session Storage
When Type "demo_user" into "#username"
And Type "secret_pass" into "#password"
And Do MFA "GAXG2MTEOR3DMMDG" into "#totpcode"
Then Assert text "Welcome!" in "h1"
And Highlight element "img#image1"
And Click 'a:contains("This Page")'
And Save screenshot to logs
When Click link "Sign out"
Then Assert element 'a:contains("Sign in")'
And Assert text "You have been signed out!"
```
🐝 If there's a test failure, that's easy to spot:
```bash
Feature: SeleniumBase scenarios for the Fail Page # features/fail_page.feature:1
Scenario: Fail test on purpose to see what happens # features/fail_page.feature:3
When Open the Fail Page # features/steps/fail_page.py:4
Then Fail test on purpose # features/steps/fail_page.py:9
Assertion Failed: This test fails on purpose!
Captured stdout:
>>> STEP FAILED: (#2) Fail test on purpose
Class / Feature: SeleniumBase scenarios for the Fail Page
Test / Scenario: Fail test on purpose to see what happens
❌ Scenario Failed!
```
🐝🎖️ For convenience, the [SeleniumBase Behave GUI](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/behave_gui.md) lets you run ``behave`` scripts from a Desktop app.
🐝🎖️ To launch it, call ``sbase behave-gui`` or ``sbase gui-behave``:
```bash
sbase behave-gui
* Starting the SeleniumBase Behave Commander GUI App...
```
<img src="https://seleniumbase.io/cdn/img/sbase_behave_gui_wide_5.png" title="SeleniumBase" width="600">
🐝🎖️ You can customize the tests that show up there:
```bash
sbase behave-gui # all tests
sbase behave-gui -i=calculator # tests with "calculator" in the name
sbase behave-gui features/ # tests located in the "features/" folder
sbase behave-gui features/calculator.feature # tests in that feature
```
--------
<div>To learn more about SeleniumBase, check out the Docs Site:</div>
<a href="https://seleniumbase.io">
<img src="https://img.shields.io/badge/docs-%20%20SeleniumBase.io-11BBDD.svg" alt="SeleniumBase.io Docs" /></a>
<div>All the code is on GitHub:</div>
<a href="https://github.com/seleniumbase/SeleniumBase">
<img src="https://img.shields.io/badge/✅%20💛%20View%20Code-on%20GitHub%20🌎%20🚀-02A79E.svg" alt="SeleniumBase on GitHub" /></a>

View File

View File

@ -0,0 +1,3 @@
[behave]
show_skipped=false
show_timings=false

View File

View File

@ -0,0 +1,3 @@
[behave]
show_skipped=false
show_timings=false

View File

@ -0,0 +1,83 @@
Feature: SeleniumBase scenarios for the Calculator App
Background:
Given Open the Calculator App
Scenario: Pressing "C" outputs "0"
When Press C
Then Verify output is "0"
Scenario: 1 + 2 + 3 + 4 + 5 = 15
When Press C
And Press 1
And Press +
And Press 2
And Press +
And Press 3
And Press +
And Press 4
And Press +
And Press 5
Then Verify output is "1+2+3+4+5"
When Press =
Then Verify output is "15"
Scenario: 6 × 7 × 8 × 9 = 3024
When Press C
And Press 6
And Press ×
And Press 7
And Press ×
And Press 8
And Press ×
And Press 9
Then Verify output is "6×7×8×9"
When Press =
Then Verify output is "3024"
Scenario: 44 - 11 = 33
When Press C
And Press 4
And Press 4
And Press -
And Press 1
And Press 1
Then Verify output is "44-11"
When Press =
Then Verify output is "33"
Scenario: 7.0 × (3 + 3) = 42
When Press C
And Press 7
And Press .
And Press 0
And Press ×
And Press (
And Press 3
And Press +
And Press 3
And Press )
Then Verify output is "7.0×(3+3)"
When Press =
Then Verify output is "42"
Scenario: 4.5 × 68 = 306
When Press C
And Evaluate [4.5 × 68]
Then Verify output is "306"
Scenario Outline: <First> ÷ <Second> = <Result>
When Press C
And Press [<First>]
And Press ÷
And Press [<Second>]
And Press =
Then Verify output is "<Result>"
Examples:
| First | Second | Result |
| 1948 | 4 | 487 |
| 21 | 0 | Error |
Scenario: Save calculator screenshot to logs
Given Press [1337]
Given Save calculator screenshot to logs

View File

@ -0,0 +1,11 @@
from seleniumbase import BaseCase
from seleniumbase.behave import behave_sb
behave_sb.set_base_class(BaseCase) # Accepts a BaseCase subclass
from seleniumbase.behave.behave_sb import before_all # noqa
from seleniumbase.behave.behave_sb import before_feature # noqa
from seleniumbase.behave.behave_sb import before_scenario # noqa
from seleniumbase.behave.behave_sb import before_step # noqa
from seleniumbase.behave.behave_sb import after_step # noqa
from seleniumbase.behave.behave_sb import after_scenario # noqa
from seleniumbase.behave.behave_sb import after_feature # noqa
from seleniumbase.behave.behave_sb import after_all # noqa

View File

@ -0,0 +1,5 @@
Feature: SeleniumBase scenarios for the Fail Page
Scenario: Fail test on purpose to see what happens
When Open the Fail Page
Then Fail test on purpose

View File

@ -0,0 +1,15 @@
Feature: SeleniumBase scenarios for the RealWorld App
Scenario: Verify RealWorld App (log in / sign out)
Given Open "seleniumbase.io/realworld/login"
And Clear Session Storage
When Type "demo_user" into "#username"
And Type "secret_pass" into "#password"
And Do MFA "GAXG2MTEOR3DMMDG" into "#totpcode"
Then Assert exact text "Welcome!" in "h1"
And Highlight "img#image1"
And Click 'a:contains("This Page")'
And Save screenshot to logs
When Click link "Sign out"
Then Assert element 'a:contains("Sign in")'
And Assert text "You have been signed out!"

View File

View File

@ -0,0 +1,144 @@
from behave import step
@step("Open the Calculator App")
def go_to_calculator(context):
context.sb.open("https://seleniumbase.io/apps/calculator")
@step("Press C")
def press_c(context):
context.sb.click("button#clear")
@step("Press (")
def press_open_paren(context):
context.sb.click('button[id="("]')
@step("Press )")
def press_close_paren(context):
context.sb.click('button[id=")"]')
@step("Press ÷")
def press_divide(context):
context.sb.click("button#divide")
@step("Press ×")
def press_multiply(context):
context.sb.click("button#multiply")
@step("Press -")
def press_subtract(context):
context.sb.click("button#subtract")
@step("Press +")
def press_add(context):
context.sb.click("button#add")
@step("Press =")
def press_equal(context):
context.sb.click("button#equal")
@step("Press 1")
def press_1(context):
context.sb.click('button[id="1"]')
@step("Press 2")
def press_2(context):
context.sb.click('button[id="2"]')
@step("Press 3")
def press_3(context):
context.sb.click('button[id="3"]')
@step("Press 4")
def press_4(context):
context.sb.click('button[id="4"]')
@step("Press 5")
def press_5(context):
context.sb.click('button[id="5"]')
@step("Press 6")
def press_6(context):
context.sb.click('button[id="6"]')
@step("Press 7")
def press_7(context):
context.sb.click('button[id="7"]')
@step("Press 8")
def press_8(context):
context.sb.click('button[id="8"]')
@step("Press 9")
def press_9(context):
context.sb.click('button[id="9"]')
@step("Press 0")
def press_0(context):
context.sb.click('button[id="0"]')
@step("Press ←")
def press_delete(context):
context.sb.click("button#delete")
@step("Press .")
def press_dot(context):
context.sb.click('button[id="."]')
@step("Press [{number}]")
def enter_number_into_calc(context, number):
sb = context.sb
for digit in number:
sb.click('button[id="%s"]' % digit)
@step("Evaluate [{equation}]")
def evaluate_equation(context, equation):
sb = context.sb
for key in equation:
if key == " ":
continue
elif key == "÷":
sb.click("button#divide")
elif key == "×":
sb.click("button#multiply")
elif key == "-":
sb.click("button#subtract")
elif key == "+":
sb.click("button#add")
else:
sb.click('button[id="%s"]' % key)
sb.click("button#equal")
@step('Verify output is "{output}"')
def verify_output(context, output):
sb = context.sb
sb.assert_exact_text(output, "#output")
@step("Save calculator screenshot to logs")
def save_calculator_screenshot_to_logs(context):
sb = context.sb
sb.save_screenshot_to_logs()

View File

@ -0,0 +1,11 @@
from behave import step
@step("Open the Fail Page")
def go_to_error_page(context):
context.sb.open("https://seleniumbase.io/error_page/")
@step("Fail test on purpose")
def fail_on_purpose(context):
context.sb.fail("This test fails on purpose!")

View File

@ -0,0 +1 @@
from seleniumbase.behave import steps # noqa

View File

@ -0,0 +1,168 @@
from behave import step
@step("Open the Swag Labs Login Page")
def go_to_swag_labs(context):
sb = context.sb
sb.open("https://www.saucedemo.com")
sb.clear_local_storage()
@step("Login to Swag Labs with {user}")
def login_to_swag_labs(context, user):
sb = context.sb
sb.type("#user-name", user)
sb.type("#password", "secret_sauce\n")
@step("Verify that the current user is logged in")
def verify_logged_in(context):
sb = context.sb
sb.assert_element("#header_container")
sb.assert_element("#react-burger-menu-btn")
sb.assert_element("#shopping_cart_container")
@step('Add "{item}" to cart')
def add_item_to_cart(context, item):
sb = context.sb
sb.click('div.inventory_item:contains("%s") button[name*="add"]' % item)
@step('Save price of "{item}" to <{var}>')
def save_price_of_item(context, item, var):
sb = context.sb
price = sb.get_text(
'div.inventory_item:contains("%s") .inventory_item_price' % item
)
sb.variables[var] = price
@step('Remove "{item}" from cart')
def remove_item_to_cart(context, item):
sb = context.sb
sb.click('div.inventory_item:contains("%s") button[name*="remove"]' % item)
@step("Verify shopping cart badge shows {number} item(s)")
def verify_badge_number(context, number):
sb = context.sb
sb.assert_exact_text(number, "span.shopping_cart_badge")
@step("Verify shopping cart badge is missing")
def verify_badge_missing(context):
sb = context.sb
sb.assert_element_not_visible("span.shopping_cart_badge")
@step("Click on shopping cart icon")
def click_shopping_cart(context):
sb = context.sb
sb.click("#shopping_cart_container a")
@step("Click Checkout")
def click_checkout(context):
sb = context.sb
sb.click("#checkout")
@step("Enter checkout info: {first_name}, {last_name}, {zip_code}")
def enter_checkout_info(context, first_name, last_name, zip_code):
sb = context.sb
sb.type("#first-name", first_name)
sb.type("#last-name", last_name)
sb.type("#postal-code", zip_code)
@step("Click Continue")
def click_continue(context):
sb = context.sb
sb.click("input#continue")
@step('Verify {quantity} "{item}"(s) in cart')
def verify_item_in_cart(context, quantity, item):
sb = context.sb
sb.assert_exact_text(
quantity,
'div.cart_item:contains("%s") div.cart_quantity' % item
)
@step('Verify cost of "{item}" is <{var}>')
def verify_cost_of_item(context, item, var):
sb = context.sb
earlier_price = sb.variables[var]
sb.assert_exact_text(
earlier_price,
'div.cart_item_label:contains("%s") .inventory_item_price' % item
)
@step("Verify item total is {item_total}")
def verify_item_total(context, item_total):
sb = context.sb
sb.assert_exact_text(
"Item total: %s" % item_total,
"div.summary_subtotal_label",
timeout=1
)
@step("Verify tax amount is {tax_amount}")
def verify_tax_amount(context, tax_amount):
sb = context.sb
sb.assert_exact_text(
"Tax: %s" % tax_amount,
"div.summary_tax_label",
timeout=1
)
@step("Verify total cost is {total_cost}")
def verify_total_cost(context, total_cost):
sb = context.sb
sb.assert_exact_text(
"Total: %s" % total_cost,
"div.summary_total_label",
timeout=1
)
@step("Click Finish")
def click_finish(context):
sb = context.sb
sb.click("button#finish")
@step("Verify order complete")
def verify_order_complete(context):
sb = context.sb
sb.assert_exact_text("THANK YOU FOR YOUR ORDER", "h2")
sb.assert_element('img[alt="Pony Express"]')
@step("Logout from Swag Labs")
def logout_from_swag_labs(context):
sb = context.sb
sb.js_click("a#logout_sidebar_link")
@step("Verify on Login page")
def verify_on_login_page(context):
sb = context.sb
sb.assert_element("#login-button")
@step("Sort items from Z to A")
def sort_items_from_z_to_a(context):
sb = context.sb
sb.select_option_by_text("select.product_sort_container", "Name (Z to A)")
@step('Verify "{item}" on top')
def verify_item_on_top(context, item):
sb = context.sb
sb.assert_text(item, "div.inventory_item_name")

View File

@ -0,0 +1,75 @@
Feature: SeleniumBase scenarios for the Swag Labs App
Background:
Given Open the Swag Labs Login Page
Scenario: User can log in and log out successfully
When Login to Swag Labs with standard_user
Then Verify that the current user is logged in
When Logout from Swag Labs
Then Verify on Login page
Scenario: User can order a backpack from the store
When Login to Swag Labs with standard_user
Then Verify that the current user is logged in
And Save price of "Backpack" to <item_price>
When Add "Backpack" to Cart
Then Verify shopping cart badge shows 1 item(s)
When Click on shopping cart icon
And Click Checkout
And Enter checkout info: First, Last, 12345
And Click Continue
Then Verify 1 "Backpack"(s) in cart
And Verify cost of "Backpack" is <item_price>
And Verify item total is $29.99
And Verify tax amount is $2.40
And Verify total cost is $32.39
When Click Finish
Then Verify order complete
When Logout from Swag Labs
Then Verify on Login page
Scenario: User can order two items from the store
When Login to Swag Labs with standard_user
And Add "Bike Light" to Cart
And Add "Fleece Jacket" to Cart
Then Verify shopping cart badge shows 2 item(s)
When Click on shopping cart icon
And Click Checkout
And Enter checkout info: First, Last, 54321
And Click Continue
Then Verify 1 "Bike Light"(s) in cart
Then Verify 1 "Fleece Jacket"(s) in cart
And Verify item total is $59.98
And Verify tax amount is $4.80
And Verify total cost is $64.78
When Click Finish
Then Verify order complete
When Logout from Swag Labs
Then Verify on Login page
Scenario: User can sort items by name from Z to A
When Login to Swag Labs with standard_user
And Sort items from Z to A
Then Verify "Test.allTheThings() T-Shirt" on top
When Logout from Swag Labs
Then Verify on Login page
Scenario: User can add & remove 6 items to/from cart
When Login to Swag Labs with standard_user
And Add "Backpack" to Cart
And Add "Bike Light" to Cart
And Add "Bolt T-Shirt" to Cart
And Add "Fleece Jacket" to Cart
And Add "Onesie" to Cart
And Add "Test.allTheThings() T-Shirt" to Cart
Then Verify shopping cart badge shows 6 item(s)
When Remove "Backpack" from Cart
And Remove "Bike Light" from Cart
And Remove "Bolt T-Shirt" from Cart
And Remove "Fleece Jacket" from Cart
And Remove "Onesie" from Cart
And Remove "Test.allTheThings() T-Shirt" from Cart
Then Verify shopping cart badge is missing
When Logout from Swag Labs
Then Verify on Login page