Automating web applications with Selenium is a must for testers. But if you’ve been working with Selenium for a while–you know that basic scripts only get you so far. You need something more. Something advanced to get better testing results.

    As your experience grows, projects will keep getting more complex. You’ll just have to learn new techniques to tackle dynamic web elements, handle multiple browsers, and see if the tests are both efficient and reliable.

    This blog is for testers who are ready to take their Selenium Python skills to the next level. 

    We’ll explore strategies that go beyond the basics. Advanced topics like sophisticated locators, handling dynamic content, organizing tests with the Page Object Model, and speeding things up with parallel execution will be discussed here.

    9 Advanced Scripting Techniques For Professional Testers

    You could be working on large-scale enterprise applications or small projects with detailed testing needs, and these techniques will undoubtedly create maintainable and efficient test automation scripts for you. 9 such techniques are mentioned below: 

    1. Advanced Locator Strategies 

    Selenium locators find elements on a web page, like buttons, text fields, or links. ‘id’, ‘name’, or ‘class_name’ are basic locators that work well with simple web pages. 

    But when things get more complicated, and you have to deal with dynamic content or elements without unique identifiers–you need more advanced locator strategies.

    CSS selectors are a flexible way to locate elements by their attributes, styles, or position in the HTML structure. XPath is a powerful method for locating elements by navigating the HTML tree. It finds elements based on their text content, attributes, and their position relative to other elements. 

    Relative locators were introduced in Selenium 4, and they find elements based on their location relative to other elements. It will locate a button that is next to or below a specific element. This is useful for situations where the element itself doesn’t have a unique identifier, but its position on the page is consistent. 

    1. Handling Dynamic Content with Waits

    Remember that in web applications, not everything loads instantly. Some elements take time to appear on the page. It’s like waiting for a button to show up after submitting a form. 

    If the Selenium script interacts with an element before it’s fully loaded, it can cause the test to fail. To avoid this, you use “waits”. 

    There are 3 types of waits that Selenium offers to handle dynamic content. Implicit, explicit, and fluent. 

    An implicit wait does not directly throw the error if it can’t find the element. It tells Selenium to wait for a certain amount of time before informing about the error. Explicit waits, on the other hand, are more targeted. Here, Selenium awaits a specific error that is conditioned. It could be waiting for an element to be clickable on the page or something else.

    Fluent waits are a type of explicit wait but are more flexible. They’ll allow you to set how often Selenium should check for the condition (polling frequency) and what exceptions to ignore during the wait.

    1. Page Object Model for Test Organization

    If you want to keep your test code organized and clean, POM is the way to go. Here, you don’t have to stack the test scripts with all the details about how to interact with your web page and stuff. You can simply create separate “page objects” for each page in your app.

    These page objects contain all the methods to interact with that specific page, like clicking buttons or entering text.

    This is an example of a basic Page Object Model: 

    class LoginPage:

       Def __init__(self, driver): 

            self.driver = driver self.username_input = driver.find_element_by_id(‘username’)

            self.password_input = driver.find_element_by_id(‘password’) 

            self.login_button = driver.find_element_by_id(‘login’) 

       def login(self, username, password): 

          self.username_input.send_keys(username)    

          self.password_input.send_keys(password) self.login_button.click()

    1. Using Headless Browsers for Faster Execution

    Headless browsers are regular browsers but they run without showing anything on the screen. They perform tasks like loading pages and clicking buttons but you won’t be able to see the browser window.  

    Headless browsers run faster than regular browsers since there’s no visual interface to load. They’re a right fit for automated testing environments like CI/CD pipelines, where speed really matters. 

    You can switch a browser to headless mode in Selenium quite effortlessly. Just add a quick option to your script, and you’re good to go.

    For Chrome:

    from selenium import webdriver 

    from selenium.webdriver.chrome.options import 

    Options options = Options() 

    options.add_argument(“–headless”) 

    driver = webdriver.Chrome(options=options)

    For Firefox: 

    from selenium import webdriver

    from selenium.webdriver.firefox.options import Options

    options = Options()

    options.add_argument(“–headless”)

    driver = webdriver.Firefox(options=options)

    1. Parallel test execution with Selenium Grid 

    If you want to run multiple tests at the same time across different machines and browsers, you need to know this technique. Selenium Grid has a central server called the “Hub” that controls the test execution. It connects to several “Nodes,” and each node runs tests on different browsers/operating systems.

    With multiple nodes, you can run your tests in parallel. Instead of testing a login feature on Chrome, Firefox, and Safari one by one, you can test on all three browsers at the same time. And the best past? This saves a lot of time! 

    1. Advanced Browser Interactions: File Uploads, Popups, and Frames 

    When we talk about advanced browser interactions in Selenium, we are talking about tasks that are more than just clicking and typing. The more advanced tasks here involve handling file uploads, dealing with popups, and working with frames. 

    Let’s talk about each of these advanced features in a little more detail. 

    The first one is file uploads. So, if your test involves uploading a file, you can’t just click a button and manually select the file. Selenium needs to do it for you! It directly interacts with file input fields.  Instead of clicking the upload button and waiting, you just tell Selenium where the file is located on your computer, and it takes care of the rest.

    Second are popups. These are just like alert boxes that disrupt your test if not handled properly. Selenium manages these alerts by switching to the popup window and either accepting or dismissing it. 

    Third are frames. Sometimes, parts of a webpage are loaded inside frames or iframes (like little windows within the main page). To interact with elements inside a frame, Selenium needs to switch its focus to that frame first.  

    1. Data-Driven Testing Using CSV and Excel 

    Data-driven testing runs the same test repeatedly but with different sets of data. That means here you don’t have to hard code values directly into the test script anymore. You can just pull the data from external files like CSV or Excel.

    A Comma-Separated Values (CSV) file holds data in rows and columns like a simple spreadsheet. Here, the lines represent a row, and the values are separated by commas. This format is used to store usernames, passwords, and other inputs. So, instead of updating the test script with new data every time, you just make changes in the CSV file. It’s an easy, flexible way to test different scenarios without doing extra work.

    Selenium reads this data, loops through it, and runs the test for each data set.

    Example: 

    import csv 

    with open(‘test_data.csv’, mode=’r’) as file:

          reader = csv.reader(file)

          for row in reader:

              # Use the data in your test

                 username = row[0]

                 password = row[1]

                # Insert test code here

    Excel files organize data in a more structured way. With their help, you can use libraries like openpyxl or pandas to read Excel files in Python. 

    Example: 

    import openpyxl

    workbook = openpyxl.load_workbook(‘test_data.xlsx’) 

    sheet = workbook.active 

    for row in sheet.iter_rows(min_row=2, values_only=True):

    username = row[0] 

    password = row[1]

     # Insert test code here

    1. Robust Error Handling and Logging

    When a test fails or something unexpected happens, error handling doesn’t let your tests crash and burn. They “handle” those errors like they’re supposed to. Here,  Python’s try-except manages errors and if something goes wrong in the try section, the code in the except section is executed. This prevents your test from failing completely.

    Logging keeps a detailed record of everything that happens during testing. If a test fails, the logs will tell you exactly where and why. 

    You can set your tests to take a screenshot every time something goes wrong. This way, you can see exactly what happened and where it failed. It makes finding and fixing the issue much easier.

    1. Integrating with Continuous Integration (CI) Pipelines

    Tools like Jenkins, GitLab CI, or CircleCI are used for CI. Just set up your CI tool to run Selenium Python tests every time new code is pushed to the repository. If the tests pass, you know the code is good. If they fail, the CI tool will provide an alert. 

    Integrating Selenium tests with CI means you don’t have to manually run tests after every code change. Here, the tests are triggered automatically. 

    Conclusion 

    These advanced scripting techniques in Selenium with Python will not only create more efficient and reliable tests but will automate complex scenarios as well. You will be able to handle dynamic web elements, implement custom waits, optimize execution speed, and advance your scripts. 

    And with time when you gain more experience and refine your skills, your ability to handle edge cases, improve test coverage, and reduce maintenance efforts will enhance as well.  

    It all comes down to one thing–the more you experiment and practice these advanced techniques, the more confident and capable you’ll become as a tester.