UI Testing with PyTest and Selenium =================================== Automated testing allows you execution of script, that doesn't require human interactions. This document helps you create and execute automated testing. This document assumes that we're testing `Web Application`, anything that runs in Browser can be automatically tested. Approach to Automated Testing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Perform actions: Click, Keying in Data etc. 2. Perform assertions: `assert` 3. Move to next test Pre-requisite ~~~~~~~~~~~~~ 1. Make a list of test cases 2. Write a description of every test case 3. Write down the expected and actual results of the test case 4. Test manually first, to ensure consistency Recording Tests ~~~~~~~~~~~~~~~ `Selenium `_ is a tool that allows us test automatically via Browser. We will be using specifically `Katalon `_, this allows us to record and export code. Installing Katalon Recorder ``````````````````````````` 1. Open Chrome/Firefox browser 2. Click on the kebab menu on the top right side of the URL bar 3. Click on more tools/Add-ons , select extensions option 4. After getting redirected to the extension page search for katalon/selenium recorder. 5. Then click on add extension, it will get added to the browser Recording Actions `````````````````` 1. Open recorder from the extension list 2. After opening the recorder, click on `new+` button on the navbar 3. Click on `+` sign on the sidebar of the recorder after a window pop-ups.Provide the test suite name and click on ok/submit button 4. After clicking on the `New button` we can provide the name of the test case. Things to remember while naming test: Make it relevant. Click on the OK button, once done 5. Now click on the `Record` button present on the navbar, this will redirect to the chrome browser 6. Now start testing/recording the test case, perform all actions as you'd normally do 7. Now switch back to the recorder app or page and click on the STOP button 8. Click on the PLAY button beside the record button, and click on the timer icon on the top right side of the page, by using the timer option the user can control the speed of the running test case Exporting Test cases ```````````````````` 1. Click on the Export button on the navbar 2. An export window will pop up 3. Select the desired scripting format `python/pytest` 4. Click on `Save as` a file or copy to clipboard paste it on some other location PyTest integration ~~~~~~~~~~~~~~~~~~ According to `Official Website `_ The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. By convention `pytest` will look for anything with `test_` extension as prefix, including all the sub-directories. Installation ```````````` 1. Run `pip install pytest` on terminal 2. Check that you installed the correct version(`pytest --version`) `pytest` allows you to configure different aspects using `conftest.py`. Typically setup and teardown functions are supported using `fixtures`. According to `official documentation `_ pytest fixtures offer dramatic improvements over the classic xUnit style of setup/teardown functions: * fixtures have explicit names and are activated by declaring their use from test functions, modules, classes or whole projects. * fixtures are implemented in a modular manner, as each fixture name triggers a fixture function which can itself use other fixtures. * fixture management scales from simple unit to complex functional testing, allowing to parametrize fixtures and tests according to configuration and component options, or to re-use fixtures across function, class, module or whole test session scopes. Following is sample setup of fixture in `conftest.py` .. code-block:: python @pytest.fixture(scope='session') def setup(request): chromedriver = "/usr/local/bin/chromedriver" print("\Initiating chrome driver") driver = webdriver.Chrome(chromedriver, chrome_options=options) session = request.node for item in session.items: cls = item.getparent(pytest.Class) setattr(cls.obj, "driver", driver) driver.implicitly_wait(30) yield driver time.sleep(2) driver.close() Here, as users can see we have used a `mark fixture` for a set up function which contains the browser/driver path, `chromedriver, chrome_options=options` are options that you can use to customize and configure a ChromeDriver session. Locators ~~~~~~~~ Locators allow us to search for element on which to perform operations on. Remember HTML is a tree, finding right element to operate on is important. Some actions that can be performed include: 1. Click on Element {E.g. Button, Links etc} 2. Input on Element {E.g. Updating Username and Password} To locate element on Web Page there are few methods: 1. Using ID: `driver.find_element_by_id("email").click()` 2. Using Class Name: `driver.find_element_by_class_name("Container").click()` 3. Using Name Attribute: `driver.find_element_by_name("password").send_keys(“test”)` 4. Using XPATH: `driver.find_element_by_xpath(//button[text()=’Ok’]).click()` 5. Using Link Text: `driver.find_element_by_link_text("Sign Out").click()` 6. Using CSS Selector: `driver.find_element_by_css_selector('p.content')` Interacting with Page ~~~~~~~~~~~~~~~~~~~~~ `Selenium's Docs on Navigating `_ shows few examples 1. Sending Keys: `element.send_keys("some text")` or `element.send_keys(" and some", Keys.ARROW_DOWN)` 2. Clearing Element: `element.clear()` 3. Clicking: `driver.find_element_by_id("submit").click()` Tips for Debugging ~~~~~~~~~~~~~~~~~~~ 1. Run every test case at least twice 2. Also run entire test suite and check behaviour of Web Application 3. Solve runtime error as soon as possible 4. Make sure your `assert` statements are corrects 5. Code Review your tests 6. Use `DRY method `_ in the tests References ~~~~~~~~~~ 1. `Location Elements `_ 2. `PyTest Examples `_ 3. `Python Selenium Documentation `_