1. Action scenario and its sequence
When you start planning an automation scenario, it's important to understand that, just like in fairy tales, you should go from simple to complex. Think of your script as a hero going on an adventure across the pages of a website. Each step is well-thought-out and carefully set up to stay on track.
Creating a step-by-step automation scenario
Start with a plan. What do you want to achieve? Load a page, fill out a form, click a button? Like they say, "Fail to plan, plan to fail." We don't want to fail, so let's write out the steps we expect to take.
from selenium import webdriver
from selenium.webdriver.common.by import By
# Create a driver instance. Use a driver suitable for your browser.
driver = webdriver.Chrome()
# Open the page
driver.get('https://example.com/login')
# Fill in the login
driver.find_element(By.NAME, 'username').send_keys('my_username')
# Fill in the password
driver.find_element(By.NAME, 'password').send_keys('my_secure_password')
# Click the login button
driver.find_element(By.ID, 'login-button').click()
Here we set the rhythm for our dance. Each step of the scenario is executed sequentially so your script can smoothly navigate the site.
Logging execution steps
Like any self-respecting hero, our script should leave traces so we know where it's been and what it did. Logging is like your script's diary. It helps track the execution of steps and identify errors if something goes wrong.
import logging
# Setting up logging
logging.basicConfig(level=logging.INFO)
# Example of logging an action
logging.info("Opening the login page")
driver.get('https://example.com/login')
Logging not only helps with debugging but also gives peace of mind, knowing your script is performing each step properly. If something goes wrong, you can go back and see where it faltered.
2. Organizing code for readability and modification
When the scenario becomes more complex, it's important to keep the code tidy. Imagine a big celebration with lots of guests and dishes: if everything is not in its place, it turns into chaos. In our case — chaos in the code.
Setting up code structure
To make changes to the code with minimal effort, it needs to be well-organized. Like a sock sorter, you need to keep everything in order. Use functions to separate repetitive actions into individual blocks.
def login_to_site(driver, username, password):
logging.info("Entering login")
driver.find_element(By.NAME, 'username').send_keys(username)
logging.info("Entering password")
driver.find_element(By.NAME, 'password').send_keys(password)
logging.info("Clicking the login button")
driver.find_element(By.ID, 'login-button').click()
# Using the function to log in
login_to_site(driver, 'my_username', 'my_secure_password')
Using functions makes the code more organized and allows you to easily make changes. For example, if the ID of the login button changes, you only need to update it in one function instead of everywhere in the code.
3. Example: Automating the purchase process on a website
Let's imagine we need to set up automation for the purchase process on a website, which includes the following steps:
- Open the website and log in to an account.
- Navigate to the product catalog and add a product to the cart.
- Go to the cart and complete the purchase.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Initialize the driver with settings
def initialize_driver():
driver = webdriver.Chrome()
driver.implicitly_wait(10) # Implicit wait
return driver
# Function for logging into the account
def login(driver, username, password):
driver.get("https://example.com")
driver.find_element_by_id("username").send_keys(username)
driver.find_element_by_id("password").send_keys(password)
driver.find_element_by_id("login_button").click()
# Function for navigating to the product catalog and adding a product to the cart
def add_product_to_cart(driver):
driver.get("https://example.com/catalog")
product = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "product_item"))
)
product.click()
add_to_cart_button = driver.find_element_by_id("add_to_cart")
add_to_cart_button.click()
# Function for going to the cart and completing the purchase
def checkout(driver):
driver.get("https://example.com/cart")
checkout_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "checkout"))
)
checkout_button.click()
# Function for closing the driver
def close_driver(driver):
driver.quit()
# Main script to execute the sequence of actions
def main():
# Set up data
username = "myusername"
password = "mypassword"
# Initialize the driver
driver = initialize_driver()
try:
# Log in to the site
login(driver, username, password)
# Navigate to the catalog and add a product to the cart
add_product_to_cart(driver)
# Go to the cart and complete the purchase
checkout(driver)
finally:
# Close the driver
close_driver(driver)
# Run the main script
main()
Explanation of functions
-
initialize_driver()— function to initialize the web driver. It sets an implicit wait for all elements and returns the driver object. -
login()— function to log in to the site. It takesusernameandpasswordas parameters, which are used to fill out the login form and click the button. -
add_product_to_cart()— function to navigate to the catalog, select a product, and add it to the cart. -
checkout()— function to go to the cart and complete the purchase. -
close_driver()— function to end the work with the driver. -
main()— main function that manages the sequence of actions. It calls all the stages and specifies the login data.
Advantages of this approach
-
Readability— each stage is designed as a separate function, simplifying code understanding. -
Reusability— individual functions can be used independently of the main script, for example, to perform specific actions on the site. -
Ease of testing— each stage can be tested separately to ensure everything works correctly. -
Flexibility— if needed, you can add other functions or change the order of actions inmain().
GO TO FULL VERSION