Skip to content

Commit 0c68192

Browse files
authored
Merge pull request #565 from seleniumbase/add-the-translator
Add the SeleniumBase Universal Translator API
2 parents 4f9b425 + 94d3aab commit 0c68192

37 files changed

+1983
-216
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## <img src="https://cdn2.hubspot.net/hubfs/100006/images/super_square_logo_3.png" title="SeleniumBase" height="32"> CHANGELOG
2+
3+
### See: [SeleniumBase/releases](https://github.com/seleniumbase/SeleniumBase/releases)

README.md

Lines changed: 37 additions & 36 deletions
Large diffs are not rendered by default.

examples/ReadMe.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
[<img src="https://cdn2.hubspot.net/hubfs/100006/images/sb_logo_dh.png" title="SeleniumBase" align="center" height="155">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
1+
<h3 align="center"><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/README.md"><img src="https://cdn2.hubspot.net/hubfs/100006/images/super_logo_sb.png" alt="SeleniumBase" height="48" /></a></h3>
22

3-
## Running Example Tests
3+
## <img src="https://cdn2.hubspot.net/hubfs/100006/images/super_square_logo_3.png" title="SeleniumBase" height="32"> **Running Example Tests:**
44

5-
SeleniumBase tests can be run with either **``pytest``** or **``nosetests``**, but using pytest is strongly recommended. Chrome is the default browser if not specified.
5+
SeleniumBase tests are run with **``pytest``** or **``nosetests``**. (<i>Using pytest is recommended.</i>) ``Chrome`` is the default browser if not specified. During test failures, logs and screenshots from the most recent test run are saved to the ``latest_logs/`` folder.
66

7-
During test failures, logs and screenshots from the most recent test run will get saved to the ``latest_logs/`` folder. Those logs will get moved to ``archived_logs/`` if you have ARCHIVE_EXISTING_LOGS set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py)
7+
(NOTE: Some example tests in this folder fail on purpose to demonstrate [logging features](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/example_logs/ReadMe.md).)
88

9-
(NOTE: Many tests in this folder fail on purpose to demonstrate the built-in logging, screenshots, and reporting features.)
9+
<a href="https://github.com/seleniumbase/SeleniumBase">
10+
<img src="https://img.shields.io/badge/tested%20with-SeleniumBase-04C38E.svg" alt="Tested with SeleniumBase" /></a>
1011

1112
**Here are some example run commands to help get you started:**
1213

@@ -24,13 +25,19 @@ Run an example test in Demo Mode: (highlight assertions)
2425
```bash
2526
pytest my_first_test.py --demo
2627
```
27-
<img src="https://cdn2.hubspot.net/hubfs/100006/images/my_first_test_gif.gif" title="SeleniumBase"><br />
28+
<img src="https://cdn2.hubspot.net/hubfs/100006/images/my_first_test_gif.gif" title="SeleniumBase Demo Mode" /><br />
2829

2930
Run an example test in Headless Mode: (invisible browser)
3031
```bash
3132
pytest my_first_test.py --headless
3233
```
3334

35+
Run an example test using Chrome's mobile device emulator: (default settings)
36+
```bash
37+
pytest test_swag_labs.py --mobile
38+
```
39+
<img src="https://cdn2.hubspot.net/hubfs/100006/images/swag_mobile.gif" title="SeleniumBase Mobile Mode" /><br />
40+
3441
Run tests with verbose output: (includes more details)
3542
```bash
3643
pytest test_suite.py -v
@@ -56,11 +63,6 @@ Run a failing test: (See the ``latest_logs/`` folder for logs and screenshots)
5663
pytest test_fail.py
5764
```
5865

59-
Run an example test using Chrome's mobile device emulator: (default settings)
60-
```bash
61-
pytest test_swag_labs.py --mobile
62-
```
63-
6466
Run a failing test with Debug-mode enabled: (``pdb`` activates on failures)
6567
```bash
6668
pytest test_fail.py --pdb -s
@@ -105,8 +107,8 @@ To make things easier, here's a simple GUI program that allows you to run a few
105107
```bash
106108
python gui_test_runner.py
107109
```
108-
<img src="https://cdn2.hubspot.net/hubfs/100006/images/gui_test_runner_py.png" title="GUI Test Runner" height="260">
110+
<img src="https://cdn2.hubspot.net/hubfs/100006/images/gui_test_runner_py.png" title="GUI Test Runner" height="260" />
109111

110112
--------
111113

112-
[<img src="https://cdn2.hubspot.net/hubfs/100006/images/super_logo_e.png" title="SeleniumBase" height="48">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
114+
<img src="https://cdn2.hubspot.net/hubfs/100006/images/SeleniumBaseText_F.png" title="SeleniumBase" height="45" />

examples/example_logs/ReadMe.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#### Logging, Screenshots, and Reports examples
1+
### <img src="https://cdn2.hubspot.net/hubfs/100006/images/super_square_logo_3a.png" title="SeleniumBase" height="32"> **Logging, Screenshots, and Reports:**
22

3-
Log files in [example_logs/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/example_logs) were generated when [test_fail.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_fail.py) ran and failed. By default, logs are saved to ``latest_logs/``. If ARCHIVE_EXISTING_LOGS is set to True in [settings.py](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/config/settings.py), past logs get saved to ``archived_logs/``.
3+
Log files in [example_logs/](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/example_logs) were generated when [test_fail.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_fail.py) ran and failed. During test failures, logs and screenshots get saved to the ``latest_logs/`` folder. If ``--archive-logs`` is set, test logs will get archived to the ``archived_logs/`` folder.
44

55
```bash
66
pytest test_fail.py --browser=chrome

examples/master_qa/ReadMe.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![](http://cdn2.hubspot.net/hubfs/100006/images/masterqa_logo-11.png "MasterQA")
22

3-
### MasterQA combines SeleniumBase automation with manual verification steps to bridge the gap between manual QA and automated QA.
3+
### MasterQA combines automation with manual verification steps.
44

55
![](https://cdn2.hubspot.net/hubfs/100006/images/masterqa6.gif "MasterQA")
66

@@ -15,9 +15,9 @@ self.highlight_update_text("input#s", "Dragons\n")
1515
self.verify('Do you see "dragons" in the search results?')
1616
```
1717

18-
After the web browser performs various automated actions, a pop-up window will ask the user questions for each verification command.
18+
After each automation checkpoint, a pop-up window will ask the user questions for each verification command.
1919

20-
At the end of a full test run, as seen from [this longer example](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/masterqa_test.py), you'll see a results page that appears after responding to all the verification questions. (Failed verifications generate links to screenshots and log files.)
20+
When the test run completes, as seen from [this longer example](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/masterqa_test.py), you'll reach the results page that appears after answering all the verification questions. (Failed verifications generate links to screenshots and log files.)
2121

2222
![](http://cdn2.hubspot.net/hubfs/100006/images/hybrid_screen.png "MasterQA")
2323

@@ -38,9 +38,9 @@ At the end of your test run, you'll receive a report with results, screenshots,
3838

3939
### Check out [masterqa_test.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/master_qa/masterqa_test.py) to learn how to write your own MasterQA tests:
4040

41-
You'll notice that tests are written based on [SeleniumBase](http://seleniumbase.com), with the key difference of using a different import: ``from seleniumbase import MasterQA`` rather than ``from seleniumbase import BaseCase``. Now the test class will import ``MasterQA`` instead of ``BaseCase``.
41+
You'll notice that tests are written the same way as regular [SeleniumBase](http://seleniumbase.com) tests, with the key difference being a different import: ``from seleniumbase import MasterQA`` rather than ``from seleniumbase import BaseCase``. Now your Python test class will import ``MasterQA`` instead of ``BaseCase``.
4242

43-
To add a manual verification step, use ``self.verify()`` in the code after each part of the script that needs manual verification. If you want to include a custom question, add text inside that call (in quotes). Example:
43+
To add a manual verification step, use ``self.verify()`` in the code after each part of your test that needs a manual verification step. If you want to include a custom question, add text inside that call (in quotes). Example:
4444

4545
```python
4646
self.verify()

examples/swag_labs_suite.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
class SwagLabsTests(BaseCase):
77

8-
def login(self, user="standard_user"):
9-
""" Login to Swag Labs and assert that the login was successful. """
10-
if user not in (["standard_user", "problem_user"]):
11-
raise Exception("Invalid user!")
8+
def login(self, username="standard_user"):
9+
""" Login to Swag Labs and verify that login was successful. """
1210
self.open("https://www.saucedemo.com/")
13-
self.update_text("#user-name", user)
11+
if username not in self.get_text("#login_credentials"):
12+
self.fail("Invalid user for login: %s" % username)
13+
self.update_text("#user-name", username)
1414
self.update_text("#password", "secret_sauce")
1515
self.click('input[type="submit"]')
1616
self.assert_element("#inventory_container")
@@ -21,11 +21,10 @@ def login(self, user="standard_user"):
2121
["problem_user"],
2222
])
2323
@pytest.mark.run(order=1)
24-
def test_swag_labs_basic_functional_flow(self, user):
25-
""" This test checks for basic functional flow in the Swag Labs store.
26-
The test is parameterized, and receives the user to use for login.
27-
"""
28-
self.login(user)
24+
def test_swag_labs_basic_functional_flow(self, username):
25+
""" This test checks functional flow of the Swag Labs store.
26+
This test is parameterized, and receives the user for login. """
27+
self.login(username=username)
2928

3029
# Verify that the "Test.allTheThings() T-Shirt" appears on the page
3130
item_name = "Test.allTheThings() T-Shirt"
@@ -34,7 +33,7 @@ def test_swag_labs_basic_functional_flow(self, user):
3433
# Verify that a reverse-alphabetical sort works as expected
3534
self.select_option_by_value("select.product_sort_container", "za")
3635
if item_name not in self.get_text("div.inventory_item"):
37-
raise Exception('Sort Failed! Expecting "%s" on top!' % item_name)
36+
self.fail('Sort Failed! Expecting "%s" on top!' % item_name)
3837

3938
# Add the "Test.allTheThings() T-Shirt" to the cart
4039
self.assert_exact_text("ADD TO CART", "button.btn_inventory")
@@ -49,7 +48,11 @@ def test_swag_labs_basic_functional_flow(self, user):
4948
self.assert_text(item_name, "div.inventory_item_name")
5049
self.assert_exact_text("1", "div.cart_quantity")
5150
self.assert_exact_text("REMOVE", "button.cart_button")
52-
self.assert_element("link=CONTINUE SHOPPING")
51+
continue_shopping_button = "link=CONTINUE SHOPPING"
52+
if self.browser == "safari":
53+
# Safari sees this element differently
54+
continue_shopping_button = "link=Continue Shopping"
55+
self.assert_element(continue_shopping_button)
5356

5457
# Checkout - Add info
5558
self.click("link=CHECKOUT")
@@ -67,23 +70,22 @@ def test_swag_labs_basic_functional_flow(self, user):
6770
self.assert_text(item_price, "div.inventory_item_price")
6871
self.assert_exact_text("1", "div.summary_quantity")
6972

70-
# Finish Checkout and verify item is no longer in cart
73+
# Finish Checkout and verify the item was removed from the cart
7174
self.click("link=FINISH")
7275
self.assert_exact_text("THANK YOU FOR YOUR ORDER", "h2")
7376
self.assert_element("div.pony_express")
7477
self.click("#shopping_cart_container path")
7578
self.assert_element_absent("div.inventory_item_name")
76-
self.click("link=CONTINUE SHOPPING")
79+
self.click(continue_shopping_button)
7780
self.assert_element_absent("span.shopping_cart_badge")
7881

7982
@parameterized.expand([
8083
["standard_user"],
8184
["problem_user"],
8285
])
8386
@pytest.mark.run(order=2)
84-
def test_swag_labs_products_page_resource_verification(self, user):
87+
def test_swag_labs_products_page_resource_verification(self, username):
8588
""" This test checks for 404 errors on the Swag Labs products page.
86-
The test is parameterized, and receives the user to use for login.
87-
"""
88-
self.login(user)
89+
This test is parameterized, and receives the user for login. """
90+
self.login(username=username)
8991
self.assert_no_404_errors()

examples/test_swag_labs.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33

44
class SwagLabsTests(BaseCase):
55

6-
def login(self, user="standard_user"):
7-
""" Login to Swag Labs and assert that the login was successful. """
8-
if user not in (["standard_user", "problem_user"]):
9-
raise Exception("Invalid user!")
6+
def login(self, username="standard_user"):
7+
""" Login to Swag Labs and verify that login was successful. """
108
self.open("https://www.saucedemo.com/")
11-
self.update_text("#user-name", user)
9+
if username not in self.get_text("#login_credentials"):
10+
self.fail("Invalid user for login: %s" % username)
11+
self.update_text("#user-name", username)
1212
self.update_text("#password", "secret_sauce")
1313
self.click('input[type="submit"]')
1414
self.assert_element("#inventory_container")
1515
self.assert_text("Products", "div.product_label")
1616

1717
def test_swag_labs_basic_flow(self):
18-
""" This test checks basic functional flow in the Swag Labs store. """
19-
self.login()
18+
""" This test checks functional flow of the Swag Labs store. """
19+
self.login(username="standard_user")
2020

2121
# Verify that the "Test.allTheThings() T-Shirt" appears on the page
2222
item_name = "Test.allTheThings() T-Shirt"
@@ -25,7 +25,7 @@ def test_swag_labs_basic_flow(self):
2525
# Verify that a reverse-alphabetical sort works as expected
2626
self.select_option_by_value("select.product_sort_container", "za")
2727
if item_name not in self.get_text("div.inventory_item"):
28-
raise Exception('Sort Failed! Expecting "%s" on top!' % item_name)
28+
self.fail('Sort Failed! Expecting "%s" on top!' % item_name)
2929

3030
# Add the "Test.allTheThings() T-Shirt" to the cart
3131
self.assert_exact_text("ADD TO CART", "button.btn_inventory")
@@ -40,7 +40,11 @@ def test_swag_labs_basic_flow(self):
4040
self.assert_text(item_name, "div.inventory_item_name")
4141
self.assert_exact_text("1", "div.cart_quantity")
4242
self.assert_exact_text("REMOVE", "button.cart_button")
43-
self.assert_element("link=CONTINUE SHOPPING")
43+
continue_shopping_button = "link=CONTINUE SHOPPING"
44+
if self.browser == "safari":
45+
# Safari sees this element differently
46+
continue_shopping_button = "link=Continue Shopping"
47+
self.assert_element(continue_shopping_button)
4448

4549
# Checkout - Add info
4650
self.click("link=CHECKOUT")
@@ -64,5 +68,5 @@ def test_swag_labs_basic_flow(self):
6468
self.assert_element("div.pony_express")
6569
self.click("#shopping_cart_container path")
6670
self.assert_element_absent("div.inventory_item_name")
67-
self.click("link=CONTINUE SHOPPING")
71+
self.click(continue_shopping_button)
6872
self.assert_element_absent("span.shopping_cart_badge")

examples/tour_examples/ReadMe.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
## SeleniumBase Website Tours
1+
<h3 align="left"><img src="https://cdn2.hubspot.net/hubfs/100006/images/super_logo_sb23.png" alt="SeleniumBase" height="48" /></h3>
22

3-
SeleniumBase Tours utilize your choice of 4 JavaScript libraries for prototyping walkthroughs on any website:<br>**[Shepherd](https://shepherdjs.dev/)**, **[Bootstrap Tour](http://bootstraptour.com/)**, **[IntroJS](https://introjs.com/)**, and **[Hopscotch](https://linkedinattic.github.io/hopscotch/)**.
3+
## Website Tours
4+
5+
SeleniumBase Tours utilize 4 JavaScript libraries for creating interactive walkthroughs on any website:<br>**[Shepherd](https://shepherdjs.dev/)**, **[Bootstrap Tour](http://bootstraptour.com/)**, **[IntroJS](https://introjs.com/)**, and **[Hopscotch](https://linkedinattic.github.io/hopscotch/)**.
46

57
**Example tour:**
68

examples/translations/ReadMe.md

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,62 @@
1-
[<img src="https://cdn2.hubspot.net/hubfs/100006/images/SeleniumBaseText_F.png" title="SeleniumBase" align="center" height="38">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
2-
### Multi-Language Tests
1+
<h3 align="left"><a href="https://github.com/seleniumbase/SeleniumBase/blob/master/README.md"><img src="https://cdn2.hubspot.net/hubfs/100006/images/super_logo_m.png" title="SeleniumBase" height="48" /></a></h3>
32

4-
#### (Python 3 Only!)
3+
### <img src="https://cdn2.hubspot.net/hubfs/100006/images/super_square_logo_3.png" title="SeleniumBase" height="32"> Multi-Language Tests (Python 3 Only!)
4+
5+
**SeleniumBase** supports the following 10 languages:
6+
* English
7+
* Chinese / 中文
8+
* Dutch / Nederlands
9+
* French / Français
10+
* Italian / Italiano
11+
* Japanese / 日本語
12+
* Korean / 한국어
13+
* Portuguese / Português
14+
* Russian / Русский
15+
* Spanish / Español
16+
17+
Multi-language tests are run with **pytest** like any other test. Every test method has a one-to-one mapping to every other supported language. Example:
18+
``self.open(URL)`` = ``self.开启网址(URL)``
19+
20+
--------
21+
22+
You can use SeleniumBase to translate any test from one language to another by using the console scripts interface:
23+
24+
```bash
25+
seleniumbase translate
26+
```
27+
28+
```
29+
* Usage:
30+
seleniumbase translate [SB_FILE].py [LANGUAGE] [ACTION]
31+
32+
* Languages:
33+
``--en`` / ``--English`` | ``--zh`` / ``--Chinese``
34+
``--nl`` / ``--Dutch`` | ``--fr`` / ``--French``
35+
``--it`` / ``--Italian`` | ``--ja`` / ``--Japanese``
36+
``--ko`` / ``--Korean`` | ``--pt`` / ``--Portuguese``
37+
``--ru`` / ``--Russian`` | ``--es`` / ``--Spanish``
38+
39+
* Actions:
40+
``-p`` / ``--print`` (Print translation output to the screen)
41+
``-o`` / ``--overwrite`` (Overwrite the file being translated)
42+
``-c`` / ``--copy`` (Copy the translation to a new ``.py`` file)
43+
44+
* Examples:
45+
Translate test_1.py into Chinese and only print the output:
46+
>>> seleniumbase translate test_1.py --zh -p
47+
Translate test_2.py into Portuguese and overwrite the file:
48+
>>> seleniumbase translate test_2.py --pt -o
49+
Translate test_3.py into Dutch and make a copy of the file:
50+
>>> seleniumbase translate test_3.py --nl -c
51+
52+
* Output:
53+
Translates a SeleniumBase Python file into the language
54+
specified. Method calls and ``import`` lines get swapped.
55+
Both a language and an action must be specified.
56+
The ``-p`` action can be paired with one other action.
57+
When running with ``-c`` (or ``--copy``) the new file name
58+
will be the orginal name appended with an underscore
59+
plus the 2-letter language code of the new language.
60+
(Example: Translating ``test_1.py`` into Japanese with
61+
``-c`` will create a new file called ``test_1_ja.py``.)
62+
```

examples/visual_testing/ReadMe.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
[<img src="https://cdn2.hubspot.net/hubfs/100006/images/SeleniumBaseText_F.png" title="SeleniumBase" align="center" height="38">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
2-
### Automated Visual Regression Testing
1+
[<img src="https://cdn2.hubspot.net/hubfs/100006/images/sb_logo_f6.png" title="SeleniumBase" align="center" height="120">](https://github.com/seleniumbase/SeleniumBase/blob/master/README.md)
32

4-
[![Automated Visual Regression Testing](http://img.youtube.com/vi/erwkoiDeNzA/3.jpg)](https://www.youtube.com/watch?v=erwkoiDeNzA "Automated Visual Regression Testing")
3+
## <img src="https://cdn2.hubspot.net/hubfs/100006/images/super_square_logo_3a.png" title="SeleniumBase" height="32"> Automated Visual Regression Testing
54

5+
[<img src="http://img.youtube.com/vi/erwkoiDeNzA/0.jpg" title="Automated Visual Regression Testing" height="180">](https://www.youtube.com/watch?v=erwkoiDeNzA)
66
(**[Watch the tutorial on YouTube](https://www.youtube.com/watch?v=erwkoiDeNzA)**)
77

88
Automated Visual Regression Testing helps you detect when the layout of a web page has changed. Rather than comparing screenshots, layout differences are detected by comparing HTML tags and attributes with a baseline. If a change is detected, it could mean that something broke, the web page was redesigned, or dynamic content changed.

0 commit comments

Comments
 (0)