In our last episode, we set up our virtual environment and installed the required packages. Today we are going to do real work as I promised. We will build a project step by step which will do the automation testing in our target application which is a quiz application. Where admin can log in and create/update/delete categories, subcategories questions, options. Nice and simple right? Well yes, and we are going to automate the testing for this application. Let’s see our modules first to understand what we are really doing.
- Homepage
- Login
- Category
- Subcategory
- Question
- Option
These are the main modules of the application which we will test and eventually we will add more modules in our list.
The Automation Testing Application Structure
As we will be using selenium with python, we need to think about our application structure. Of course, we will be using the modular pattern. And one thing I want you all to keep in mind is, writing bad code is a sin, and making your project structure messy is also a sin. If I do that sin, please punish me any way you like. I will respectfully accept that. Always be careful with that. And today we will test the homepage of that quiz application. So for that our automation testing application’s folder and file structure will be like this:
. ├── application │ ├── app.py │ ├── __init__.py │ └── utils │ ├── constants.py │ ├── __init__.py │ └── urls.py ├── homepage │ ├── homepage.py │ ├── __init__.py ├── README.md ├── requirements.txt └── settings.py └── .env
Application package: This is the core module of our application. You see that we have a sub-package in our application package which is utils. We will use it for string constants and URLs and helping function later.
homepage package: This is where our homepage automation code will be.
settings.py: We will keep our application settings here.
.env: env is for user credential or any kind of secret data of our application.
Let’s Start Automating the Homepage
First of all, on our homepage most of the cases there will be a navbar, Some sections like about-us and many more. Our target is to test the homepage according to our testing requirements. So let’s meet our requirements first:
- Visit the homepage of the quiz application if the main URL is working or not.
- Check the navbar items if it contains all the elements. In our case, they are Home, About Us, Feature, How It Works, and Sign In.
- Check if navbar items are clickable on fullscreen and they are taking us on specific sections.
- Check if navbar items are clickable on the custom window size like mobile and they are taking us on specific sections.
[ Step:01 ] Add Constants And URLs In Our Application
In our application/utils/urls.py file let’s add the homepage URL.
HOMEPAGE_URL = "https://querkiz.itech-theme.com/"
Now let’s add these constants in our application/utils/constants.py file.
HOMEPAGE_NAV_BAR = ["Home", "About Us", "Feature", "How It Works", "Sign In"] FULL_WINDOW_NAV_ITEMS_X_PATH = [ '//*[@id="nav_menu"]/li[2]/a', '//*[@id="nav_menu"]/li[3]/a', '//*[@id="nav_menu"]/li[4]/a', '//*[@id="scrolltop"]/a' ] MOBILE_MENU_NAV_BAR_X_PATH = '//*[@id="scrolltop"]/header/div/div/div/div[' '3]/div/div/a ' MOBILE_SCREEN_NAV_ITEMS_X_PATH = [ '//*[@id="scrolltop"]/header/div/div/div/div[3]/div/div/nav/ul/li[2]/a', '//*[@id="scrolltop"]/header/div/div/div/div[3]/div/div/nav/ul/li[3]/a', '//*[@id="scrolltop"]/header/div/div/div/div[3]/div/div/nav/ul/li[4]/a', '//*[@id="scrolltop"]/a' ]
Now we understand that HOMEPAGE_NAV_BAR is an array of navbar element’s names. But what is FULL_WINDOW_NAV_ITEMS_X_PATH? What is X Path first of all? Well, the Full form of X Path is the XML path. And we can find any element from a webpage using it. Now let’s explain the constants.
FULL_WINDOW_NAV_ITEMS_X_PATH is an array of XPaths of navbar elements when the window size is large.
MOBILE_MENU_NAV_BAR_X_PATH is the XPath of the navbar menu when the window size is small.
MOBILE_SCREEN_NAV_ITEMS_X_PATH is an array of XPaths of navbar elements when the window size is small.
A demo of finding XPath is in the below video so that you can get XPath easily.
[ Step: 02 ] Install Packages For Further Development
Before installing packages, let’s activate our virtual environment first. Run this below command from the virtual environment directory.
. bin/activate
Now run these below commands to install our project dependencies.
pip install python-dotenv pip install termcolor
And I’m sure you have installed python selenium package from our previous episode.
[ Step: 03 ] Developing Homepage Package
Write those below codes in our homepage/homepage.py file.
from time import sleep from selenium import webdriver from termcolor import colored from application.utils.constants import FULL_WINDOW_NAV_ITEMS_X_PATH, MOBILE_SCREEN_NAV_ITEMS_X_PATH, MOBILE_MENU_NAV_BAR_X_PATH class HomepageTest: """ Automate homepage visiting process """ def __init__(self, url: str, nav_bar_elements: list): """ :param url: url of the web application :param nav_bar_elements: nav bar elements of the web application """ self._browser = webdriver.Chrome() self._browser.maximize_window() self.url = url self.nav_bar_elements = nav_bar_elements def visit_homepage(self) -> bool: """ Visit the web application's given homepage url :return: bool """ try: self._browser.get(self.url) console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Homepage OK!]', 'cyan') print(console_message) sleep(5) return True except Exception as e: console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Homepage not OK', 'cyan') print(console_message) print(colored(str(e), 'red')) return False def nav_bar_content_testing(self) -> bool: """ Test nav bar has all desired elements :return: bool """ try: nav_menu = self._browser.find_element_by_id("nav_menu") nav_list = nav_menu.find_elements_by_tag_name('li') nav_element_matched = self.compare_nav_elements(nav_list) console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav bar OK!]', 'cyan') print(console_message) return nav_element_matched except Exception as e: console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav bar is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False def compare_nav_elements(self, nav_list) -> bool: """ Compare given nav list and web page nav list :param nav_list: Fetched from web page :return: bool """ nav_elements_to_check = [] for li in nav_list: nav_elements_to_check.append(li.text) nav_has_all_menu = all(element in self.nav_bar_elements for element in nav_elements_to_check) return nav_has_all_menu def click_nav_elements_on_fullscreen(self) -> bool: """ This will test nav bar element by clicking on their link while window size is in full screen :return: bool """ try: for element in FULL_WINDOW_NAV_ITEMS_X_PATH: self.click_on_element(element) sleep(2) console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav elements link OK!]', 'cyan') print(console_message) return True except Exception as e: console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav elements link is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False def click_nav_elements_on_mobile_screen(self) -> bool: """ This will test nav bar element by clicking on their link after decreasing window size :return: bool """ try: self.set_window_screen() self.click_on_element(MOBILE_MENU_NAV_BAR_X_PATH) for element in MOBILE_SCREEN_NAV_ITEMS_X_PATH: self.click_on_element(element) console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav elements link on full screen OK!]', 'cyan') print(console_message) return True except Exception as e: console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav elements link on mobile screen is ' 'not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False def click_on_element(self, x_path: str): """ Will click on given x_path of html element :param x_path: x_path of html element """ element = self._browser.find_element_by_xpath(x_path) element.click() sleep(1) def set_window_screen(self) -> bool: """ This method is resize the browser window :return: bool """ try: sleep(2) self._browser.set_window_size(400, 862) console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Custom window size OK!]', 'cyan') print(console_message) return True except Exception as e: console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Custom window size is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False def close_browser(self): """ Close the browser """ self._browser.quit()
[ Step: 04 ] Code Breakdown & Explanation
Lets breakdown all the methods and codes to understand what has been done and why we will extend our code base with more features. We have used try-except to handle any unwanted exceptions. Always remember to handle exceptions.
Initialize the attributes of HomepageTest class
In our __init__ method we are initializing url and nav_bar_elements. Also, we have initialized our web driver as _browser. Let’s break more,
self._browser = webdriver.Chrome()
This is how we will initiate our web driver. And we used the Chrome web driver.
Visit Homepage
Our visit_homepage() method is responsible for visiting the given url. We will hit the homepage URL.
self._browser.get(self.url)
Print the message with style.
console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Homepage OK!]', 'cyan') print(console_message)
Wait for 5 seconds.
sleep(5)
Test Navbar Elements
Our nav_bar_content_testing() method is responsible for comparing the navbar elements with the given navbar elements. First, select the main navbar.
nav_menu = self._browser.find_element_by_id("nav_menu")
find_element_by_id() will find the element in HTML DOM with given ID. Now let’s get all the list items from nav_menu.
nav_list = nav_menu.find_elements_by_tag_name('li')
find_elements_by_tag_name() will find all the HTML elements with the given tag name. Now check if the nav_list texts match with given navbar items from the constants.
nav_element_matched = self.compare_nav_elements(nav_list)
compare_nav_elements() is our class method witch will compare two lists and returns boolean. Again, print a nice message.
console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav bar OK!]', 'cyan') print(console_message)
If things went wrong then print error message in except block with color like this.
console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav bar is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red'))
Close the browser and return False.
self.close_browser() return False
close_browser() is our class method and inside it, we closed our browser with the below method.
self._browser.quit()
Click Navbar Elements On Fullscreen
Our click_nav_elements_on_fullscreen() is responsible for clicking the nav elements to test if they are working well on fullscreen. We made another method click_on_element() to follow DRY(Don’t repeat yourself) principle. This method will be only responsible for clicking on the element for the given x_path.
Iterated throw FULL_WINDOW_NAV_ITEMS_X_PATH and clicked on the nav items.
for element in FULL_WINDOW_NAV_ITEMS_X_PATH: self.click_on_element(element)
Wait for 2 seconds.
sleep(2)
Print nice color message and return True.
console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav elements link OK!]', 'cyan') print(console_message) return True
If anything went wrong then print the colored error messages, close the browser and return False.
console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav elements link is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False
Resize Window
The set_window_screen() will simply resize the window size. Resize the window with 400, 862 widths and height but before that wait for 2 seconds.
sleep(2) self._browser.set_window_size(768, 1024)
Print a nice colored message and return True
console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Custom window size OK!]', 'cyan') print(console_message) return True
If anything goes wrong then print the colored error message, close browser, and return False.
console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Custom window size is not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False
Click Navbar Elements On Mobile Screen
The click_nav_elements_on_mobile_screen() method is responsible for operating the same navbar element testing but only in small screen size. First, invoke the window resize method.
self.set_window_screen()
Click the navbar menu with the XPath
self.click_on_element(MOBILE_MENU_NAV_BAR_X_PATH)
And iterate through MOBILE_SCREEN_NAV_ITEMS_X_PATH and click every element.
for element in MOBILE_SCREEN_NAV_ITEMS_X_PATH: self.click_on_element(element)
Print the nice colored message and return True
console_message = colored('[success] ', 'green', attrs=['bold']) + colored( '[Nav elements link on full screen OK!]', 'cyan') print(console_message) return True
If anything goes wrong then print a colored error message, close the browser and return False.
console_message = colored('[failed] ', 'red', attrs=['bold']) + colored('Nav elements link on mobile screen is ' 'not OK!', 'cyan') print(console_message) print(colored(str(e), 'red')) self.close_browser() return False
[ Step:05 ] It’s Time, Run The Automation
In our core package application, we will run the homepage automation testing. Write the below codes in the application/app.py file.
from homepage.homepage import HomepageTest from application.utils.urls import HOMEPAGE_URL from application.utils.constants import HOMEPAGE_NAV_BAR if __name__ == '__main__': homepage = HomepageTest(HOMEPAGE_URL, HOMEPAGE_NAV_BAR) homepage.visit_homepage() homepage.nav_bar_content_testing() homepage.click_nav_elements_on_fullscreen() homepage.click_nav_elements_on_mobile_screen() homepage.close_browser()
Explanation
- Import all the things we need.
from homepage.homepage import HomepageTest from application.utils.urls import HOMEPAGE_URL from application.utils.constants import HOMEPAGE_NAV_BAR
- Create an object of the HomepageTest class.
homepage = HomepageTest(HOMEPAGE_URL, HOMEPAGE_NAV_BAR)
- Run the automation testing methods of the HomepageTest class, step by step.
homepage.visit_homepage() homepage.nav_bar_content_testing() homepage.click_nav_elements_on_fullscreen() homepage.click_nav_elements_on_mobile_screen()
- Finally, close the browser.
homepage.close_browser()
Demo Of Successful Automation Testing
Conclusion
Congratulation, you have done well. Want some more in your project? Well, why don’t you add some more requirements? You can check the headings of all sections. We have basically demonstrated click events and fetching information from the HTML DOM. We will automate the boring login in our next episode. Where our tool automatically types in input fields. Sounds exciting right? I will keep my promise. Till then practice what you have learned, stay at home. Feel free to share this article and ask anything you like. Stay tuned!
You will find all the codes in my Github repository.