├── .idea ├── .gitignore ├── PytestTutorials.iml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── DemoFirstTest ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-311.pyc │ ├── first_run_test.cpython-311-pytest-7.2.0.pyc │ ├── test_assertions.cpython-311-pytest-7.2.0.pyc │ └── test_first_run.cpython-311-pytest-7.2.0.pyc └── first_run_test.py ├── DemoPytest ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-311.pyc │ ├── test_assertions_hard.cpython-311-pytest-7.2.0.pyc │ ├── test_assertions_soft.cpython-311-pytest-7.2.0.pyc │ ├── test_fixtures.cpython-311-pytest-7.2.0.pyc │ ├── test_fixtures_2.cpython-311-pytest-7.2.0.pyc │ ├── test_markers_group.cpython-311-pytest-7.2.0.pyc │ ├── test_multiple_subset_form.cpython-311-pytest-7.2.0.pyc │ ├── test_multiple_subset_iphone.cpython-311-pytest-7.2.0.pyc │ ├── test_parameters.cpython-311-pytest-7.2.0.pyc │ └── test_parameters_2.cpython-311-pytest-7.2.0.pyc ├── geckodriver.log ├── test_assertions_hard.py ├── test_assertions_soft.py ├── test_cross_browser.py ├── test_fail.py ├── test_fixtures_1.py ├── test_fixtures_2.py ├── test_markers_group.py ├── test_multiple_subset_form.py ├── test_multiple_subset_iphone.py ├── test_parameters_1.py ├── test_parameters_2.py ├── test_skip.py └── test_stop.py ├── __pycache__ └── conftest.cpython-311-pytest-7.2.0.pyc ├── conftest.py ├── main.py ├── pages ├── __init__.py ├── base_page.py ├── change_password_page.py ├── login_page.py └── my_account_page.py ├── pytest.ini ├── tests ├── __init__.py ├── base_test.py ├── test_change_password.py └── test_login.py └── utilities ├── __init__.py ├── locators.py └── test_data.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/PytestTutorials.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /DemoFirstTest/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoFirstTest/__init__.py -------------------------------------------------------------------------------- /DemoFirstTest/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoFirstTest/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /DemoFirstTest/__pycache__/first_run_test.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoFirstTest/__pycache__/first_run_test.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoFirstTest/__pycache__/test_assertions.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoFirstTest/__pycache__/test_assertions.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoFirstTest/__pycache__/test_first_run.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoFirstTest/__pycache__/test_first_run.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoFirstTest/first_run_test.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | 3 | def test_lambdatest_playground(): 4 | driver = webdriver.Chrome() 5 | driver.maximize_window() 6 | driver.get("https://www.lambdatest.com/selenium-playground/") 7 | print("Title: ", driver.title) 8 | 9 | def test2_lambdatest_ecommerce(): 10 | driver = webdriver.Chrome() 11 | driver.maximize_window() 12 | driver.get("https://ecommerce-playground.lambdatest.io/") 13 | print("Title: ", driver.title) 14 | 15 | def testRexWebsite(): 16 | driver = webdriver.Chrome() 17 | driver.maximize_window() 18 | driver.get("https://rexjones2.com") 19 | print("Title: ", driver.title) 20 | 21 | def google_test(): 22 | driver = webdriver.Chrome() 23 | driver.maximize_window() 24 | driver.get("https://google.com") 25 | print("Title: ", driver.title) 26 | -------------------------------------------------------------------------------- /DemoPytest/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__init__.py -------------------------------------------------------------------------------- /DemoPytest/__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_assertions_hard.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_assertions_hard.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_assertions_soft.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_assertions_soft.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_fixtures.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_fixtures.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_fixtures_2.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_fixtures_2.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_markers_group.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_markers_group.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_multiple_subset_form.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_multiple_subset_form.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_multiple_subset_iphone.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_multiple_subset_iphone.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_parameters.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_parameters.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/__pycache__/test_parameters_2.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/DemoPytest/__pycache__/test_parameters_2.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /DemoPytest/geckodriver.log: -------------------------------------------------------------------------------- 1 | 1673230054863 geckodriver INFO Listening on 127.0.0.1:55664 2 | 1673230057910 mozrunner::runner INFO Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "55665" "--remote-allow-hosts" "localhost" "-no-remote" "-profile" "C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileaxyYDz" 3 | 1673230058588 Marionette INFO Marionette enabled 4 | 1673230058594 Marionette INFO Listening on port 55677 5 | Read port: 55677 6 | WebDriver BiDi listening on ws://127.0.0.1:55665 7 | 1673230058874 RemoteAgent WARN TLS certificate errors will be ignored for this session 8 | console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileaxyYDz\\search.json.mozlz4", (void 0))) 9 | DevTools listening on ws://127.0.0.1:55665/devtools/browser/0f9b8816-2fd8-4a1d-a4bf-f54a4ff33090 10 | 1673230063661 Marionette INFO Stopped listening on port 55677 11 | 1673230258599 geckodriver INFO Listening on 127.0.0.1:55979 12 | 1673230261633 mozrunner::runner INFO Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "55980" "--remote-allow-hosts" "localhost" "-no-remote" "-profile" "C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileg1pPLK" 13 | 1673230262165 Marionette INFO Marionette enabled 14 | 1673230262171 Marionette INFO Listening on port 55992 15 | Read port: 55992 16 | WebDriver BiDi listening on ws://127.0.0.1:55980 17 | 1673230262448 RemoteAgent WARN TLS certificate errors will be ignored for this session 18 | console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileg1pPLK\\search.json.mozlz4", (void 0))) 19 | DevTools listening on ws://127.0.0.1:55980/devtools/browser/316aef71-1e41-4c57-a282-c587485ecb93 20 | 1673230267011 Marionette INFO Stopped listening on port 55992 21 | 1678243550011 geckodriver INFO Listening on 127.0.0.1:61598 22 | 1678243553051 mozrunner::runner INFO Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "61599" "--remote-allow-hosts" "localhost" "-no-remote" "-profile" "C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileHQ0tS9" 23 | console.warn: services.settings: Ignoring preference override of remote settings server 24 | console.warn: services.settings: Allow by setting MOZ_REMOTE_SETTINGS_DEVTOOLS=1 in the environment 25 | 1678243553480 Marionette INFO Marionette enabled 26 | Dynamically enable window occlusion 0 27 | 1678243553486 Marionette INFO Listening on port 61608 28 | Read port: 61608 29 | WebDriver BiDi listening on ws://127.0.0.1:61599 30 | 1678243553609 RemoteAgent WARN TLS certificate errors will be ignored for this session 31 | console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileHQ0tS9\\search.json.mozlz4", (void 0))) 32 | DevTools listening on ws://127.0.0.1:61599/devtools/browser/9093b034-1ed1-4352-858d-3f0e566256d2 33 | 1678243558848 Marionette INFO Stopped listening on port 61608 34 | Dynamically enable window occlusion 1 35 | 1678243672818 geckodriver INFO Listening on 127.0.0.1:61800 36 | 1678243675863 mozrunner::runner INFO Running command: "C:\\Program Files\\Mozilla Firefox\\firefox.exe" "--marionette" "--remote-debugging-port" "61801" "--remote-allow-hosts" "localhost" "-no-remote" "-profile" "C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileT6hAf2" 37 | console.warn: services.settings: Ignoring preference override of remote settings server 38 | console.warn: services.settings: Allow by setting MOZ_REMOTE_SETTINGS_DEVTOOLS=1 in the environment 39 | 1678243676181 Marionette INFO Marionette enabled 40 | Dynamically enable window occlusion 0 41 | 1678243676186 Marionette INFO Listening on port 61809 42 | Read port: 61809 43 | WebDriver BiDi listening on ws://127.0.0.1:61801 44 | 1678243676305 RemoteAgent WARN TLS certificate errors will be ignored for this session 45 | console.warn: SearchSettings: "get: No settings file exists, new profile?" (new NotFoundError("Could not open the file at C:\\Users\\RexJo\\AppData\\Local\\Temp\\rust_mozprofileT6hAf2\\search.json.mozlz4", (void 0))) 46 | DevTools listening on ws://127.0.0.1:61801/devtools/browser/2bd75a89-c83d-4516-ad04-3848c9f88115 47 | 1678243681757 Marionette INFO Stopped listening on port 61809 48 | Dynamically enable window occlusion 1 49 | -------------------------------------------------------------------------------- /DemoPytest/test_assertions_hard.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.by import By 3 | 4 | class AssertionsTest(): 5 | pass 6 | 7 | def test_lambdatest_radio_button_demo_value(): 8 | driver = webdriver.Chrome() 9 | driver.maximize_window() 10 | driver.get("https://www.lambdatest.com/selenium-playground/radiobutton-demo") 11 | driver.find_element(By.XPATH, 12 | "//h4[contains(text(),'Gender')]" 13 | "//following::input[@value='Male']").click() 14 | driver.find_element(By.XPATH, 15 | "//h4[contains(text(),'Age Group')]" 16 | "//following::input[@value='15 - 50']").click() 17 | driver.find_element(By.XPATH, 18 | "//button[text()='Get values']").click() 19 | gender = driver.find_element(By.CSS_SELECTOR, 20 | ".genderbutton").text 21 | age_group = driver.find_element(By.CSS_SELECTOR, 22 | ".groupradiobutton").text 23 | print("Gender Object: \t", id(gender)) 24 | print("Male Object: \t", id("Male")) 25 | assert gender is "Male", "Gender Is Not Correct" 26 | assert driver.title.__contains__("Selenium Grid Online") 27 | assert "51" in age_group, "Age Group Is Not Correct" 28 | -------------------------------------------------------------------------------- /DemoPytest/test_assertions_soft.py: -------------------------------------------------------------------------------- 1 | import softest 2 | from selenium import webdriver 3 | from selenium.webdriver.common.by import By 4 | 5 | class AssertionsTest(softest.TestCase): 6 | pass 7 | 8 | def test_lambdatest_radio_button_demo_value(self): 9 | driver = webdriver.Chrome() 10 | driver.maximize_window() 11 | driver.get("https://www.lambdatest.com/selenium-playground/radiobutton-demo") 12 | driver.find_element(By.XPATH, 13 | "//h4[contains(text(),'Gender')]" 14 | "//following::input[@value='Male']").click() 15 | driver.find_element(By.XPATH, 16 | "//h4[contains(text(),'Age Group')]" 17 | "//following::input[@value='15 - 50']").click() 18 | driver.find_element(By.XPATH, 19 | "//button[text()='Get values']").click() 20 | gender = driver.find_element(By.CSS_SELECTOR, 21 | ".genderbutton").text 22 | age_group = driver.find_element(By.CSS_SELECTOR, 23 | ".groupradiobutton").text 24 | print("Gender Object: \t", id(gender)) 25 | print("Male Object: \t", id("Male")) 26 | self.soft_assert(self.assertIs, 27 | "Male", gender, "Gender Is Not Correct") 28 | self.soft_assert(self.assertTrue, 29 | driver.title.__contains__("Selenium Grid Online")) 30 | self.soft_assert(self.assertIn, 31 | "51", age_group, "Age Group Is Not Correct") 32 | self.assert_all("Verify Gender, Title, & Age Group") 33 | -------------------------------------------------------------------------------- /DemoPytest/test_cross_browser.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.by import By 3 | import pytest 4 | 5 | @pytest.mark.usefixtures("driver_initialization") 6 | class BaseClass: 7 | pass 8 | 9 | class TestSeleniumGrid(BaseClass): 10 | def test_lambdatest_remaining_checkboxes(self): 11 | driver = webdriver.Chrome() 12 | driver.get("https://lambdatest.github.io/sample-todo-app/") 13 | driver.find_element(By.XPATH, "//input[@name='li3']").click() 14 | remaining_checkboxes = driver.find_element\ 15 | (By.CSS_SELECTOR, "span.ng-binding").text 16 | assert remaining_checkboxes == "4 of 5 remaining" 17 | -------------------------------------------------------------------------------- /DemoPytest/test_fail.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | class Test_Math: 4 | def test_divide_number(self): 5 | pytest.xfail("Need To Investigate") 6 | num = 10 7 | result = num + num 8 | assert result == num / num 9 | 10 | @pytest.mark.xfail(reason="Result Add Numbers & Not Multiply Numbers") 11 | def test_square_number(self): 12 | num = 10 13 | result = num + num # 10 * 10 = 100 14 | assert result == num ** 2 15 | 16 | @pytest.mark.xfail(reason="Result & Assert Are Correct") 17 | def test_cube_number(self): 18 | num = 10 19 | result = num * num * num # 10 * 10 * 10 = 1000 20 | assert result == num ** 3 21 | 22 | @pytest.mark.xfail(run=False) 23 | def test_number_square(self): 24 | num = 10 25 | result = num * num # 10 * 10 = 100 26 | assert result == num ** 2 27 | -------------------------------------------------------------------------------- /DemoPytest/test_fixtures_1.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | from selenium.webdriver.common.by import By 4 | 5 | driver = webdriver.Chrome() 6 | 7 | @pytest.fixture(autouse=True) 8 | def start_automatic_fixture(): 9 | print("Start Test With Automatic Fixture") 10 | 11 | @pytest.fixture() 12 | def setup_teardown(): 13 | driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/login") 14 | driver.find_element(By.ID, "input-email")\ 15 | .send_keys("PytestSelenium@Gmail.com") 16 | driver.find_element(By.ID, "input-password")\ 17 | .send_keys("@1234PytestSelenium") 18 | driver.find_element(By.XPATH, 19 | "//input[@value='Login']").click() 20 | print("Log In") 21 | yield 22 | driver.find_element(By.PARTIAL_LINK_TEXT, 23 | "Logout").click() 24 | print("Log Out") 25 | 26 | def test1_order_history_title(setup_teardown): 27 | driver.find_element(By.PARTIAL_LINK_TEXT, 28 | "Order").click() 29 | assert driver.title == "Order History" 30 | print("Test 1 Is Complete") 31 | 32 | def test2_change_password_title(setup_teardown): 33 | driver.find_element(By.PARTIAL_LINK_TEXT, 34 | "Password").click() 35 | assert driver.title == "Change Password" 36 | print("Test 2 Is Complete") 37 | -------------------------------------------------------------------------------- /DemoPytest/test_fixtures_2.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | from selenium.webdriver.common.by import By 4 | 5 | driver = webdriver.Chrome() 6 | 7 | @pytest.fixture(autouse=True) 8 | def start_automatic_fixture(): 9 | print("Start Test With Automatic Fixture") 10 | 11 | @pytest.fixture(scope="function") 12 | def setup_teardown(): 13 | driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=account/login") 14 | driver.find_element(By.ID, "input-email")\ 15 | .send_keys("PytestSelenium@Gmail.com") 16 | driver.find_element(By.ID, "input-password")\ 17 | .send_keys("@1234PytestSelenium") 18 | driver.find_element(By.XPATH, 19 | "//input[@value='Login']").click() 20 | print("Log In") 21 | yield 22 | driver.find_element(By.PARTIAL_LINK_TEXT, 23 | "Logout").click() 24 | print("Log Out") 25 | 26 | @pytest.mark.usefixtures("setup_teardown") 27 | def test1_order_history_title(): 28 | driver.find_element(By.PARTIAL_LINK_TEXT, 29 | "Order").click() 30 | assert driver.title == "Order History" 31 | print("Test 1 Is Complete") 32 | 33 | @pytest.mark.usefixtures("setup_teardown") 34 | def test2_change_password_title(): 35 | driver.find_element(By.PARTIAL_LINK_TEXT, 36 | "Password").click() 37 | assert driver.title == "Change Password" 38 | print("Test 2 Is Complete") 39 | -------------------------------------------------------------------------------- /DemoPytest/test_markers_group.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | from selenium.webdriver.common.by import By 4 | 5 | pytestmark = [pytest.mark.regression, pytest.mark.sanity] 6 | # pytestmark = pytest.mark.regression 7 | 8 | @pytest.mark.integration 9 | @pytest.mark.smoke 10 | def test_lambdatest_ajax_form(): 11 | driver = webdriver.Chrome() 12 | driver.maximize_window() 13 | driver.get("https://www.lambdatest.com/selenium-playground/ajax-form-submit-demo") 14 | driver.find_element(By.ID, "title")\ 15 | .send_keys("Pytest Tutorial") 16 | driver.find_element(By.ID, "description")\ 17 | .send_keys("LambdaTest Selenium Playground") 18 | driver.find_element(By.ID, "btn-submit").click() 19 | request = driver.find_element(By.ID, 20 | "submit-control").text 21 | assert request.__contains__("Processing") 22 | 23 | def test_e2e(): 24 | print("End To End Test") 25 | 26 | @pytest.mark.smoke 27 | def test_login(): 28 | print("Log Into Application") 29 | 30 | @pytest.mark.smoke 31 | def test_logout(): 32 | print("Log Out Application") 33 | -------------------------------------------------------------------------------- /DemoPytest/test_multiple_subset_form.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.by import By 3 | 4 | def test_lambdatest_simple_form_demo(): 5 | driver = webdriver.Chrome() 6 | driver.maximize_window() 7 | driver.get("https://www.lambdatest.com/selenium-playground/simple-form-demo") 8 | driver.find_element(By.XPATH, 9 | "//input[@id='user-message']")\ 10 | .send_keys("Pytest Is A Test Framework") 11 | driver.find_element(By.ID, "showInput").click() 12 | message = driver.find_element(By.ID, "message").text 13 | assert message == "Pytest Is A Test Framework" 14 | -------------------------------------------------------------------------------- /DemoPytest/test_multiple_subset_iphone.py: -------------------------------------------------------------------------------- 1 | from selenium import webdriver 2 | from selenium.webdriver.common.by import By 3 | 4 | def test_search_lambdatest_ecommerce(): 5 | driver = webdriver.Chrome() 6 | driver.maximize_window() 7 | driver.get("https://ecommerce-playground.lambdatest.io/") 8 | driver.find_element(By.XPATH, 9 | "//input[@placeholder='Search For Products']")\ 10 | .send_keys("iPhone") 11 | driver.find_element(By.XPATH, 12 | "//button[text()='Search']").click() 13 | search_value = driver.find_element(By.XPATH, 14 | "//h1[contains(text(),'Search')]").text 15 | assert "iPhone" in search_value 16 | 17 | def test_add_to_cart(): 18 | result = 1 19 | print("Add To Cart") 20 | assert result == 3 21 | -------------------------------------------------------------------------------- /DemoPytest/test_parameters_1.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | from selenium import webdriver 4 | from selenium.webdriver.common.by import By 5 | import pytest 6 | 7 | @pytest.mark.parametrize("num1, num2, expected_total", 8 | [ 9 | ("25", "25", "50"), 10 | ("10", "10", "30"), 11 | ("30", "40", "70") 12 | ]) 13 | def test_lambdatest_two_input_fields(num1, num2, expected_total): 14 | driver = webdriver.Chrome() 15 | driver.maximize_window() 16 | driver.get("https://www.lambdatest.com/selenium-playground/simple-form-demo") 17 | driver.find_element(By.ID, "sum1").send_keys(num1) 18 | driver.find_element(By.ID, "sum2").send_keys(num2) 19 | driver.find_element(By.XPATH, 20 | "//button[text()='Get values']").click() 21 | actual_total = driver.find_element(By.ID, "addmessage").text 22 | assert actual_total == expected_total, \ 23 | "Actual & Expected Totals Do Not Match" 24 | 25 | @pytest.mark.parametrize("base", [1, 2, 3]) 26 | @pytest.mark.parametrize("exponent", [4, 5, 6]) 27 | def test_raising_base_to_power(base, exponent): 28 | result = base ** exponent 29 | assert result == math.pow(base, exponent) 30 | -------------------------------------------------------------------------------- /DemoPytest/test_parameters_2.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium.webdriver.common.by import By 3 | 4 | @pytest.mark.usefixtures("initialize_driver") 5 | class BaseClass: 6 | pass 7 | 8 | class Test_Drivers(BaseClass): 9 | def test_multiple_browsers(self): 10 | self.driver.get("https://www.lambdatest.com/selenium-playground/") 11 | header = self.driver.find_element(By.CSS_SELECTOR, 12 | "div#__next h1").text 13 | print("Header: ", header) 14 | assert header == "Selenium Playground" 15 | -------------------------------------------------------------------------------- /DemoPytest/test_skip.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import pytest 4 | from selenium import webdriver 5 | 6 | 7 | class TestLambdaTest: 8 | def test_sample_app_title(self): 9 | driver = webdriver.Chrome() 10 | driver.get("https://lambdatest.github.io/sample-todo-app/") 11 | pytest.skip() 12 | expected_title = "Sample page - lambdatest.com" 13 | assert expected_title == driver.title 14 | 15 | @pytest.mark.skip(reason="Code Has Not Been Deployed") 16 | def test_ecommerce_title(self): 17 | driver = webdriver.Chrome() 18 | driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=product/category&path=17") 19 | expected_title = "Software" 20 | assert expected_title == driver.title 21 | 22 | @pytest.mark.skip() 23 | def test_special_offers(self): 24 | driver = webdriver.Chrome() 25 | driver.get("https://ecommerce-playground.lambdatest.io/index.php?route=product/special") 26 | expected_title = "Special Offers" 27 | assert expected_title == driver.title 28 | 29 | @pytest.mark.skipif( 30 | datetime.now() <= datetime(2099, 12, 31), 31 | reason="Repo Is Not Complete Until After Finishing Tutorial") 32 | def test_pytest_github_repo(self): 33 | driver = webdriver.Chrome() 34 | driver.get("https://github.com/RexJonesII/PytestTutorials") 35 | expected_title = "RexJonesII" 36 | print("Title: ", expected_title) 37 | assert driver.title.__contains__(expected_title) 38 | -------------------------------------------------------------------------------- /DemoPytest/test_stop.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | # @pytest.mark.skip(reason="Demonstrate How To Skip A Class") 4 | # @pytest.mark.xfail (reason="Demonstrate How To XFAIL/XPASS A Class") 5 | class Test_Math: 6 | # Pass 7 | def test_number_square(self): 8 | num = 10 9 | result = num * num # 10 * 10 = 100 10 | assert result == num ** 2 11 | 12 | def test_divide_number(self): 13 | # Fail 14 | num = 10 15 | result = num + num 16 | assert result == num / num 17 | 18 | # Fail 19 | def test_square_number(self): 20 | num = 10 21 | result = num + num # 10 * 10 = 100 22 | assert result == num ** 2 23 | 24 | # Pass 25 | def test_cube_number(self): 26 | num = 10 27 | result = num * num * num # 10 * 10 * 10 = 1000 28 | assert result == num ** 3 29 | -------------------------------------------------------------------------------- /__pycache__/conftest.cpython-311-pytest-7.2.0.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/__pycache__/conftest.cpython-311-pytest-7.2.0.pyc -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from selenium import webdriver 3 | from selenium.webdriver.remote.remote_connection import RemoteConnection 4 | 5 | from utilities.test_data import TestData 6 | 7 | @pytest.fixture(params=["chrome", "firefox", "edge"]) 8 | def initialize_driver(request): 9 | if request.param == "chrome": 10 | driver = webdriver.Chrome() 11 | elif request.param == "firefox": 12 | driver = webdriver.Firefox() 13 | elif request.param == "edge": 14 | driver = webdriver.Edge() 15 | request.cls.driver = driver 16 | print("Browser: ", request.param) 17 | driver.get(TestData.url) 18 | driver.maximize_window() 19 | yield 20 | print("Close Driver") 21 | driver.close() 22 | 23 | # 1st Step: Declare Variables For Setting Up LambdaTest 24 | user_name = "Rex.Jones" 25 | access_token = "YxU1eSK0Cx3WkN7d2FouJ4agNhPUiw8yOrXWAF8TN19LvOueVB" 26 | remote_url = "https://" + user_name + ":" + access_token + "@hub.lambdatest.com/wd/hub" 27 | 28 | # 2nd Step: Define The Desired Capabilities (3 Caps) 29 | chrome_caps = { 30 | "build" : "1.0", 31 | "name" : "LambdaTest Grid On Chrome", 32 | "platform" : "Windows 10", 33 | "browserName" : "Chrome", 34 | "version" : "latest" 35 | } 36 | 37 | firefox_caps = { 38 | "build" : "2.0", 39 | "name" : "LambdaTest Grid On Firefox", 40 | "platform" : "Windows 10", 41 | "browserName" : "Firefox", 42 | "version" : "latest" 43 | } 44 | 45 | edge_caps = { 46 | "build" : "3.0", 47 | "name" : "LambdaTest Grid On Edge", 48 | "platform" : "Windows 10", 49 | "browserName" : "Edge", 50 | "version" : "latest" 51 | } 52 | 53 | #3rd Step: Connect To LambdaTest Using A Fixture & RemoteConnection 54 | @pytest.fixture(params=["chrome", "firefox", "edge"]) 55 | def driver_initialization(request): 56 | """ 57 | Initialize Driver For Selenium Grid On LambdaTest 58 | :param request: 59 | """ 60 | desired_caps = {} 61 | 62 | if request.param == "chrome": 63 | desired_caps.update(chrome_caps) 64 | driver = webdriver.Remote( 65 | command_executor=RemoteConnection(remote_url), 66 | desired_capabilities={"LT:Options":desired_caps}) 67 | elif request.param == "firefox": 68 | desired_caps.update(firefox_caps) 69 | driver = webdriver.Remote( 70 | command_executor=RemoteConnection(remote_url), 71 | desired_capabilities={"LT:Options": desired_caps}) 72 | elif request.param == "edge": 73 | desired_caps.update(edge_caps) 74 | driver = webdriver.Remote( 75 | command_executor=RemoteConnection(remote_url), 76 | desired_capabilities={"LT:Options": desired_caps}) 77 | request.cls.driver = driver 78 | yield 79 | driver.close() 80 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # This is a sample Python script. 2 | 3 | # Press Shift+F10 to execute it or replace it with your code. 4 | # Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. 5 | 6 | 7 | def print_hi(name): 8 | # Use a breakpoint in the code line below to debug your script. 9 | print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. 10 | 11 | 12 | # Press the green button in the gutter to run the script. 13 | if __name__ == '__main__': 14 | print_hi('PyCharm') 15 | 16 | # See PyCharm help at https://www.jetbrains.com/help/pycharm/ 17 | -------------------------------------------------------------------------------- /pages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/pages/__init__.py -------------------------------------------------------------------------------- /pages/base_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | 3 | 4 | class BasePage: 5 | """ 6 | The Purpose Of A BasePage Is To Contain Methods Common To All Page Objects 7 | """ 8 | def __init__(self, driver): 9 | self.driver = driver 10 | 11 | def find(self, *locator): 12 | return self.driver.find_element(*locator) 13 | 14 | def click(self, locator): 15 | self.find(*locator).click() 16 | # self.driver.find_element(*locator).click() 17 | 18 | def set(self, locator, value): 19 | self.find(*locator).clear() 20 | self.find(*locator).send_keys(value) 21 | 22 | def get_text(self, locator): 23 | return self.find(*locator).text 24 | 25 | def get_title(self): 26 | return self.driver.title 27 | 28 | def click_right_menu_page(self, page_name): 29 | # self.click(self.page(page_name)) 30 | page = By.XPATH, "//aside[@id='column-right']//a[text()=' "+ page_name +"']" 31 | self.click(page) 32 | 33 | # Below Method Allows Us To Click Page, Check If Page Is Visible, & More Actions 34 | def page(self, page_name): 35 | return By.XPATH, "//aside[@id='column-right']//a[text()=' "+ page_name +"']" 36 | -------------------------------------------------------------------------------- /pages/change_password_page.py: -------------------------------------------------------------------------------- 1 | from pages.base_page import BasePage 2 | from pages.my_account_page import MyAccountPage 3 | from utilities.locators import ChangePasswordLocatorFields 4 | 5 | 6 | class ChangePasswordPage(BasePage): 7 | 8 | def __init__(self, driver): 9 | self.locate = ChangePasswordLocatorFields 10 | super().__init__(driver) 11 | 12 | def change_password(self, password, confirm_password): 13 | self.set(self.locate.password_field, password) 14 | self.set(self.locate.confirm_password_field, confirm_password) 15 | self.click(self.locate.continue_button) 16 | return MyAccountPage(self.driver) 17 | 18 | def get_confirmation_error_message(self): 19 | return self.get_text(self.locate.confirmation_error_message) 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /pages/login_page.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | 3 | from pages.base_page import BasePage 4 | from pages.my_account_page import MyAccountPage 5 | 6 | 7 | class LoginPage(BasePage): 8 | email_address_field = (By.ID, "input-email") 9 | password_field = (By.ID, "input-password") 10 | login_button = (By.XPATH, "//div[@id='content']//input[@value='Login']") 11 | warning_message = (By.CSS_SELECTOR, "#account-login .alert-danger") 12 | 13 | def __init__(self, driver): 14 | super().__init__(driver) 15 | 16 | def set_email_address(self, email_address): 17 | self.set(self.email_address_field, email_address) 18 | # self.driver.find_element(self.email_address_field).send_keys(email_address) 19 | 20 | def set_password(self, password): 21 | self.set(self.password_field, password) 22 | 23 | def click_login_button(self): 24 | self.click(self.login_button) 25 | return MyAccountPage(self.driver) 26 | 27 | def log_into_application(self, email, password): 28 | self.set_email_address(email) 29 | self.set_password(password) 30 | self.click_login_button() 31 | 32 | def get_warning_message(self): 33 | return self.get_text(self.warning_message) 34 | -------------------------------------------------------------------------------- /pages/my_account_page.py: -------------------------------------------------------------------------------- 1 | from pages.base_page import BasePage 2 | 3 | class MyAccountPage(BasePage): 4 | pass 5 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | markers = 3 | smoke: Smoke Test 4 | regression: Regression Test 5 | sanity 6 | integration: 7 | addopts = -rA -v --html=AutomatonPytestReport.html 8 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/tests/__init__.py -------------------------------------------------------------------------------- /tests/base_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | @pytest.mark.usefixtures("initialize_driver") 4 | class BaseTest: 5 | pass -------------------------------------------------------------------------------- /tests/test_change_password.py: -------------------------------------------------------------------------------- 1 | from pages.change_password_page import ChangePasswordPage 2 | from pages.login_page import LoginPage 3 | from tests.base_test import BaseTest 4 | from utilities.test_data import TestData 5 | 6 | class TestChangePassword(BaseTest): 7 | 8 | def test_changing_password(self): 9 | login_page = LoginPage(self.driver) 10 | change_password_page = ChangePasswordPage(self.driver) 11 | expected_message = "Password confirmation does not match password!" 12 | login_page.set_email_address(TestData.email) 13 | login_page.set_password(TestData.password) 14 | my_account_page = login_page.click_login_button() 15 | my_account_page.click_right_menu_page("Password") 16 | change_password_page.change_password( 17 | "InvalidPassword", "InvalidConfirmPassword") 18 | actual_message = change_password_page.get_confirmation_error_message() 19 | assert actual_message == expected_message 20 | -------------------------------------------------------------------------------- /tests/test_login.py: -------------------------------------------------------------------------------- 1 | from pages.login_page import LoginPage 2 | from tests.base_test import BaseTest 3 | from utilities.test_data import TestData 4 | 5 | 6 | class TestLogin(BaseTest): 7 | 8 | def test_valid_credentials(self): 9 | login_page = LoginPage(self.driver) 10 | login_page.set_email_address(TestData.email) 11 | login_page.set_password(TestData.password) 12 | login_page.click_login_button() 13 | actual_title = login_page.get_title() 14 | assert actual_title == "My Account" 15 | 16 | def test_invalid_credentials(self): 17 | login_page = LoginPage(self.driver) 18 | login_page.log_into_application( 19 | "Invalid Email", "Invalid Password") 20 | actual_message = login_page.get_warning_message() 21 | assert actual_message.__contains__("Warning") 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /utilities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RexJonesII/PytestTutorials/565fa3045533b57823c8946d2137b1e2ca7318fb/utilities/__init__.py -------------------------------------------------------------------------------- /utilities/locators.py: -------------------------------------------------------------------------------- 1 | from selenium.webdriver.common.by import By 2 | 3 | class ChangePasswordLocatorFields: 4 | password_field = (By.ID, "input-password") 5 | confirm_password_field = (By.ID, "input-confirm") 6 | continue_button = (By.XPATH, "//div[@id='content']//input[@value='Continue']") 7 | confirmation_error_message = (By.CSS_SELECTOR, "#content .text-danger") 8 | -------------------------------------------------------------------------------- /utilities/test_data.py: -------------------------------------------------------------------------------- 1 | 2 | class TestData: 3 | url = "https://ecommerce-playground.lambdatest.io/index.php?route=account/login" 4 | email = "PytestSelenium@GMail.com" 5 | password = "@1234PytestSelenium" 6 | --------------------------------------------------------------------------------