<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Idowu Omisola</title>
    <description>The latest articles on DEV Community by Idowu Omisola (@idowuomisolapaul).</description>
    <link>https://dev.to/idowuomisolapaul</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F994305%2Fc542eeb6-0418-475c-be6d-1ed03d83b338.jpeg</url>
      <title>DEV Community: Idowu Omisola</title>
      <link>https://dev.to/idowuomisolapaul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idowuomisolapaul"/>
    <language>en</language>
    <item>
      <title>How To Press Enter Without WebElement In Selenium Python</title>
      <dc:creator>Idowu Omisola</dc:creator>
      <pubDate>Sun, 21 Jul 2024 17:34:22 +0000</pubDate>
      <link>https://dev.to/testmuai/how-to-press-enter-without-webelement-in-selenium-python-mn9</link>
      <guid>https://dev.to/testmuai/how-to-press-enter-without-webelement-in-selenium-python-mn9</guid>
      <description>&lt;p&gt;The Selenium WebDriver is an indispensable testing framework with many interactive features for automating web actions. However, the standard WebDriver methods of interacting with a web page may sometimes need to be revised to test specific features.&lt;/p&gt;

&lt;p&gt;For instance, a web page that renders content asynchronously or dynamically may not arrange responses in order. Hence, using the WebDriver directly without a wrapper might be inefficient in interacting successfully with its web elements during &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt;.&lt;br&gt;
Your test scenario might also involve automating interactions such as mouse clicks, keyboard actions, and animated gestures sometimes. Leveraging the WebDriver’s *execute_script *method helps in such cases. And if your test needs to perform low-level gestures like dragging and dropping, &lt;a href="https://www.lambdatest.com/blog/handling-keyboard-actions-in-selenium-webdriver/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium’s &lt;em&gt;ActionChains&lt;/em&gt; class&lt;/a&gt; also comes in handy as a wrapper class to aid such actions.&lt;/p&gt;

&lt;p&gt;Selenium’s &lt;em&gt;ActionChains&lt;/em&gt; and &lt;em&gt;execute_script&lt;/em&gt; are handy for automating a website’s response to keyboard and mouse actions and animated cursor gestures.&lt;/p&gt;

&lt;p&gt;In this blog, I’ll show you how to press enter without WebElement in &lt;a href="https://www.lambdatest.com/learning-hub/python-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium Python&lt;/a&gt; using &lt;em&gt;ActionChains *and *execute_script&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are ActionChains in Selenium?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;ActionChains&lt;/em&gt; is a built-in class in Selenium for automating low-level interaction with the &lt;a href="https://www.lambdatest.com/blog/document-object-model/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;DOM&lt;/a&gt;. It arranges actions in a queue and features mouse actions, including click events, cursor, and touch gestures. It also supports keyboard simulations for pressing the keypads. Thus, it provides ways to interact with a web page like a regular user.&lt;/p&gt;

&lt;p&gt;Although Selenium’s &lt;em&gt;ActionChains&lt;/em&gt; queues actions sequentially in order of programmatic arrangement, it fires them at once when executed. Hence, unlike the conventional &lt;a href="https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;WebDriver&lt;/a&gt; method, the success of the entire test step depends on each action step. Once a step fails, it invalidates the whole.&lt;/p&gt;

&lt;p&gt;You might navigate a web page without using &lt;a href="https://www.lambdatest.com/learning-hub/css-selectors?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;CSS Selectors&lt;/a&gt; in &lt;em&gt;ActionChains&lt;/em&gt;. But this may be time-consuming and confusing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ActionChains&lt;/em&gt; are typically easier to use if a web page handles only one action, such as filling out a focused form with a blinking cursor. Overall, &lt;em&gt;ActionChains&lt;/em&gt; is intuitive and sensitive to component actions.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;action.send_keys(data)&lt;/em&gt; method; for example, automatically locates a focused form field to insert the specified information:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
data = "omisola"
action.send_keys(data).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For instance, automating a search query on a web page that loads only a search box with a blinking cursor requires the following actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inputting the search term using the &lt;em&gt;send_keys&lt;/em&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press the &lt;em&gt;Enter key&lt;/em&gt; to submit the search query.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, web interaction using the &lt;em&gt;ActionChains&lt;/em&gt; can be complex when automating several steps that involve moving between elements to execute several actions, including clicks, gestures, sending keys, and pressing the Tab and Enter keys, among many others.&lt;br&gt;
In the next section of this blog on how to press enter without WebElement in Selenium Python, we will explore pros and cons of &lt;em&gt;ActionChains.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Boost Your Mobile App’s Performance! Discover Proven Strategies for &lt;a href="https://www.lambdatest.com/learning-hub/mobile-performance-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Mobile Performance Testing&lt;/a&gt;. Increase User Satisfaction &amp;amp; Rankings. Get Results Fast!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Pros of the ActionChains
&lt;/h2&gt;

&lt;p&gt;Here’s why the &lt;em&gt;ActionChains&lt;/em&gt; class is handy for testing a website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;ActionChains&lt;/em&gt; object stores automated actions in a queue to execute them sequentially in order of programmatic arrangement. This is helpful when you need to perform a large sequence of actions at a go.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It includes mouse functionality, such as clicking and performing gestures for drag-and-drop actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It simulates human keyboard actions like &lt;em&gt;Tab&lt;/em&gt;, &lt;em&gt;Shift&lt;/em&gt;, &lt;em&gt;Enter&lt;/em&gt;, &lt;em&gt;Ctrl&lt;/em&gt;, &lt;em&gt;PgUp&lt;/em&gt;, and &lt;em&gt;PgDn&lt;/em&gt;, among others, to navigate to any position within the DOM.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Cons of the ActionChains
&lt;/h2&gt;

&lt;p&gt;Although the &lt;em&gt;ActionChains&lt;/em&gt; class lets you test a website using an array of actions, it has some shortcomings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Test steps depend on each other since actions are in a chain queue. Thus, once a step fails, it invalidates the entire chain, causing the test to fail without clarity about the point of failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;ActionChains&lt;/em&gt; can be hard to debug since it’s hard to tell which step in the chain causes the error.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s consider some use cases of each approach before we discuss how to press enter without WebElement in Selenium Python. However, we need to first inspect the web elements:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ANuiOzISc_T52uNJ4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ANuiOzISc_T52uNJ4.jpg" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ActionChains example use cases
&lt;/h2&gt;

&lt;p&gt;In this blog section on how to press enter without WebElement in Selenium Python, shown below are the snippets of basic usage examples of &lt;em&gt;ActionChains&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;How to create an &lt;em&gt;ActionChains&lt;/em&gt; object:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;1. Drag and drop an element using the &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
driver.get("https://www.lambdatest.com/selenium-playground/drag-and-drop-demo")
draggable = driver.find_element(By.ID, "draggable")
dropZone = driver.find_element(By.ID, "droppable")
action.drag_and_drop(draggable, dropZone).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;2. Double-click an element in &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;xoffset&lt;/em&gt; is an integer defining the pixel distance for left and right positions across the web page, while &lt;em&gt;yoffset&lt;/em&gt; is an integer defining the pixel distance for vertical (up and down) movement across the web page.&lt;/p&gt;

&lt;p&gt;The example below holds down the right mouse pad to drag the &lt;em&gt;draggable&lt;/em&gt; to 150 pixels to the right and releases the mouse at the specified position to drop the held item:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
draggable = driver.find_element(By.ID, "draggable")
action.drag_and_drop_by_offset(draggable, 150, 0).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Perform a click event using &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;from selenium.webdriver import Keys, ActionChains&lt;br&gt;
action = ActionChains()&lt;br&gt;
driver = webdriver.Chrome()&lt;br&gt;
element = driver.find_element(By.LINK_TEXT, "LambdaTest")&lt;br&gt;
action.click(element).perform()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Double-click an element in &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;from selenium.webdriver import Keys, ActionChains&lt;br&gt;
action = ActionChains()&lt;br&gt;
driver = webdriver.Chrome()&lt;br&gt;
element = driver.find_element(By.LINK_TEXT, "LambdaTest")&lt;br&gt;
action.double_click(element).perform()&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;5. Right-click an element in* ActionChains *(context-click).&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
element = driver.find_element(By.LINK_TEXT, "LambdaTest")
action.context_click(element).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;6. Click and hold an element.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
element = driver.find_element(By.LINK_TEXT, "LambdaTest")
action.click_and_hold(element).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;7. Send keys and press the Enter key using the &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web page&lt;/strong&gt;: &lt;a href="https://www.lambdatest.com/selenium-playground/simple-form-demo?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;https://www.lambdatest.com/selenium-playground/simple-form-demo.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web page inspection:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This guide focuses on &lt;a href="https://www.lambdatest.com/learning-hub/test-automation-metrics?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test automation metrics&lt;/a&gt;, its significance, strategies, challenges, and key test automation metrics for measuring success.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AG6gujeK-FuConNVX.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AG6gujeK-FuConNVX.jpg" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
driver.get("https://www.lambdatest.com/selenium-playground/simple-form-demo")
password = driver.find_elemnt(By.ID, "user-message")
action.send_keys(password)
action.send_keys(Keys.ENTER).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;8. Press the Tab key using the &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver import Keys, ActionChains
action = ActionChains()
driver = webdriver.Chrome()
password = driver.find_elemnt(By.ID, "user-message")
action.send_keys(password)
action.send_keys(Keys.TAB).perform()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Perform an action on key-up or key-down in &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;action.key_down(Keys.CONTROL).send_keys('Idowu').key_up(Keys.CONTROL).perform()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Move to a specific element:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;from selenium.webdriver import Keys, ActionChains&lt;br&gt;
action = ActionChains()&lt;br&gt;
driver = webdriver.Chrome()&lt;br&gt;
inputform = driver.find_element(By.ID, "user-message")&lt;br&gt;
action.move_to_element(inputform)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Move the mouse relative to an element by offset.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;from selenium.webdriver import Keys, ActionChains&lt;br&gt;
action = ActionChains()&lt;br&gt;
driver = webdriver.Chrome()&lt;br&gt;
inputform = driver.find_element(By.ID, "user-message")&lt;br&gt;
action.move_to_element_with_offset(inputform, 100, 200).perform()&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Move the mouse to a specific location by offset.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;action.move_by_offset(100, 200)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  What is the execute_script method in Selenium?
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;execute_script&lt;/em&gt; is a Selenium WebDriver method that allows the execution of JavaScript events and actions in the current window. It involves embedding pure JavaScript as a string into Python to modify the DOM.&lt;/p&gt;

&lt;p&gt;While the &lt;em&gt;execute_script&lt;/em&gt; method makes automation testing more flexible with browser API access, it’s easier with a knowledge of JavaScript.&lt;/p&gt;

&lt;p&gt;Since it’s JavaScript, if you don’t want to use &lt;a href="https://www.lambdatest.com/learning-hub/selenium-locators?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium locators&lt;/a&gt;, you can use JavaScript’s document queries like &lt;em&gt;getElementById *or&lt;/em&gt; getElementByClassName* to get web elements.&lt;/p&gt;

&lt;p&gt;For example, the conventional locator takes the following form for locating an element by its ID:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element = driver.find_element(By.ID, element_id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;However, the &lt;em&gt;execute_script&lt;/em&gt; method takes the following form:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element = driver.execute_script(“document.getElementById(‘user-message’);”)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In this blog on how to press enter without WebElement in Selenium Python, we’ll combine JavaScript’s &lt;em&gt;querySelector&lt;/em&gt; and the &lt;em&gt;XPath&lt;/em&gt; methods to interact with the web page elements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Learn the ins and outs of &lt;a href="https://www.lambdatest.com/learning-hub/test-execution-engine?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test execution engines &lt;/a&gt;through our extensive guide, and enhance your testing workflow with automation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Pros of the execute_script method
&lt;/h2&gt;

&lt;p&gt;Here’s why you want to use the &lt;em&gt;execute_script&lt;/em&gt; method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since JavaScript has access to browser APIs, the &lt;em&gt;execute_script&lt;/em&gt; method allows you to manipulate the DOM directly. For instance, you can leverage the embedded JavaScript to scroll to a particular position on a web page, insert an element into the DOM, get the website’s domain name, or even refresh the browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s also suitable for testing applications and websites that render content asynchronously and dynamically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since all modern browsers support JavaScript, the &lt;em&gt;execute_script&lt;/em&gt; method can confer better &lt;a href="https://www.lambdatest.com/learning-hub/cross-browser-compatibility?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;cross-browser compatibility&lt;/a&gt;, as you can use JavaScript to tweak events to suit the test browser.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Cons of execute_script method
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;JavaScript is the language of the web. So using this automation method can introduce vulnerabilities to a website.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JavaScript embedding can be hard to read, especially if you’re from a Python background with little or no knowledge of JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  execute_script example use cases
&lt;/h2&gt;

&lt;p&gt;This section on press enter without WebElement in Selenium Python discusses some applications of the *execute_script *method:&lt;/p&gt;

&lt;p&gt;Here’s the basic syntax of &lt;em&gt;execute_script&lt;/em&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;driver.execute_script(script)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Spin up an alert browser window using &lt;em&gt;execute_script&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;driver.execute_script(“alert(‘this is a test’);”)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type a text into an input field:&lt;/p&gt;

&lt;p&gt;driver.get("&lt;a href="https://www.lambdatest.com/selenium-playground/checkbox-demo%22" rel="noopener noreferrer"&gt;https://www.lambdatest.com/selenium-playground/checkbox-demo"&lt;/a&gt;)&lt;br&gt;
driver.execute_script("document.getElementById('user-message').value='Idowu paul';")&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click an element (e.g., a button):&lt;/p&gt;

&lt;p&gt;button = driver.execute_script(“return document.getElementById(‘showInput’);”)&lt;br&gt;
driver.execute_script(“arguments[0].click()”, button)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Handle a checkbox using Boolean:&lt;/p&gt;

&lt;p&gt;driver.get(“&lt;a href="https://www.lambdatest.com/selenium-playground/checkbox-demo%22" rel="noopener noreferrer"&gt;https://www.lambdatest.com/selenium-playground/checkbox-demo"&lt;/a&gt;)&lt;br&gt;
driver.execute_script(“document.getElementById(‘isAgeSelected’).checked=true;”)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To learn more about it, you can go through our earlier blog on &lt;a href="https://www.lambdatest.com/blog/how-to-select-multiple-checkboxes-in-selenium-webdriver/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;handling checkboxes in Selenium.&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Get the domain name of a website:&lt;/p&gt;

&lt;p&gt;domain_name = str(driver.execute_script("return document.domain;"))&lt;br&gt;
print(domain_name)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new element in the DOM:&lt;/p&gt;

&lt;p&gt;driver.execute_script("var element=document.createElement('newButton');"&lt;br&gt;
                      +"document.body.appendChild(element);")&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Refresh a web page using execute_script in Selenium WebDriver:&lt;/p&gt;

&lt;p&gt;driver.get("&lt;a href="https://www.lambdatest.com/selenium-playground/checkbox-demo%22" rel="noopener noreferrer"&gt;https://www.lambdatest.com/selenium-playground/checkbox-demo"&lt;/a&gt;)&lt;br&gt;
driver.execute_script("history.go(0)")&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get the height and width of a web page:&lt;/p&gt;

&lt;p&gt;driver.get("&lt;a href="https://www.lambdatest.com/selenium-playground/checkbox-demo%22" rel="noopener noreferrer"&gt;https://www.lambdatest.com/selenium-playground/checkbox-demo"&lt;/a&gt;)&lt;br&gt;
page_height = str(driver.execute_script("return window.innerHeight;"))&lt;br&gt;
page_width = str(driver.execute_script("return window.innerWidth;"))&lt;br&gt;
print(page_height)&lt;br&gt;
print(page_width)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This guide explores &lt;a href="https://www.lambdatest.com/learning-hub/digital-transformation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Digital Transformation&lt;/a&gt;, its benefits, goals, importance and challenges involved in Digital Transformation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Demonstration: Using ActionChains and execute_script
&lt;/h2&gt;

&lt;p&gt;In this section of our tutorial on press enter with WebElements in Selenium Python, I’ll demonstrate the test cases using the &lt;em&gt;ActionChains&lt;/em&gt; class and the &lt;em&gt;execute_script&lt;/em&gt; method in different code files. Both are a part of Selenium. So you don’t need to install them separately once you install Selenium.&lt;/p&gt;

&lt;p&gt;We’ll also use the &lt;a href="https://www.lambdatest.com/learning-hub/selenium-pytest-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium pytest&lt;/a&gt; module for the test execution.&lt;/p&gt;

&lt;p&gt;Our test website is &lt;a href="https://ecommerce-playground.lambdatest.io/index.php?route=account/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest’s eCommerce playground.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initially, we will showcase the process of navigating the registration page using Selenium’s *ActionChains *in a sequential manner. After understanding the functioning of the previous demonstration, we will proceed to repeat the test utilizing the *execute_script *method from Selenium WebDriver.&lt;/p&gt;

&lt;p&gt;So this blog on how to press enter without WebElement in Selenium Python assumes you’ve already installed Python on your local machine. Our test cases in this blog use Python 3.10. You can follow pretty well using earlier versions, though.&lt;/p&gt;

&lt;p&gt;We’ll also use VSCode for our &lt;a href="https://www.lambdatest.com/learning-hub/test-suite?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test suite &lt;/a&gt;development in this blog on press enter without WebElement in Selenium Python. But you can stick to an IDE that works best for you.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KZstMSOHIvQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Don’t miss out on thе latеst tutorials on automation tеsting! Subscribe to thе &lt;a href="https://www.youtube.com/c/LambdaTest?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=youtube" rel="noopener noreferrer"&gt;LambdaTеst YouTubе Channеl &lt;/a&gt;for tutorials on &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Sеlеnium tеsting&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/playwright-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Playwright testing&lt;/a&gt;, and more&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Dependencies
&lt;/h2&gt;

&lt;p&gt;To set the ground for this automation testing, you must first install Selenium and pytest in your Python virtual environment. We’ll also mask dependencies using the environment variable (.env file). So you might want to include &lt;em&gt;python-dotenv&lt;/em&gt; in your dependencies list.&lt;/p&gt;

&lt;p&gt;Create a requirements.txt file in your project root directory and list the following packages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — requirements.txt&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
selenium
python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, run the following in your command line to install the listed packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The dependencies install as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2844%2F0%2Aw8BUL1Nr0jdXV6wN.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2844%2F0%2Aw8BUL1Nr0jdXV6wN.jpg" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up a pytest Configuration file
&lt;/h2&gt;

&lt;p&gt;This blog section on press enter without WebElement in Selenium Python, we will see how to set up a pytest configuration file.&lt;/p&gt;

&lt;p&gt;While it’s not a requirement, a pytest configuration file (&lt;em&gt;pytest.ini&lt;/em&gt;) allows you to define more behaviors for your &lt;a href="https://www.lambdatest.com/blog/what-is-test-environment/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test environment&lt;/a&gt;. For instance, you can use this file to declare how you want your test to log results in the terminal or inside a log file.&lt;/p&gt;

&lt;p&gt;This file executes before other test files since it contains the test configurations and resides in the root directory.&lt;/p&gt;

&lt;p&gt;In this case, we’ll ignore deprecation warnings using the &lt;em&gt;pytest.ini&lt;/em&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — pytest.ini&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[pytest]
filterwarnings = ignore::DeprecationWarning
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;pytest.ini&lt;/em&gt; file has other configuration options besides ignoring deprecation warnings. But note that it doesn’t work without the [&lt;em&gt;pytest&lt;/em&gt;] entry point — as written above.&lt;/p&gt;

&lt;p&gt;For instance, among other settings, you can use it to configure the command-line outputs and custom-exit test execution once the test fails n times. You can also use it to point to your settings file while testing websites developed with complex web frameworks like Django locally. You can learn more about it through this tutorial on &lt;a href="https://www.lambdatest.com/blog/pytest-django-tutorial/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;pytest Django&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are a few more configuration options for &lt;em&gt;pytest.ini&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Console_output_styl*e= **progress (default)&lt;/em&gt;&lt;em&gt;, **classic&lt;/em&gt;&lt;em&gt;, or **count&lt;/em&gt;&lt;em&gt;. Specify any of these options to customize how Pytest displays results. For example, while **progress&lt;/em&gt;* loads test results using percentages, &lt;strong&gt;count&lt;/strong&gt; displays the number of tests executed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;faulthandler_timeout&lt;/em&gt; = 10; exits the test after a 10-second timeout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;log_auto_indent&lt;/em&gt; = &lt;strong&gt;Boolean&lt;/strong&gt;; choose whether to allow auto-indentation of CLI logs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;log_cli&lt;/em&gt; = &lt;strong&gt;Boolean&lt;/strong&gt;; specify whether or not you want to see execution logs during test executions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;*log_file *= log/log FileName.txt; write test logs into a file in your project root directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;log_file_date_format&lt;/em&gt; = %Y-%m-%d %H:%M:%S; append test time and date to log files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;log_level&lt;/em&gt; = INFO; specify the log type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In this article, we will delve into the fundamentals of &lt;a href="https://www.lambdatest.com/learning-hub/quality-assurance?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Quality Assurance&lt;/a&gt;, its key principles, methodologies, and its vital role in delivering excellence.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;This section on press enter without WebElement in Selenium Python shows the entire test suite structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test_directory
├─ .gitignore
├─ pytest.ini
├─ README.md
├─ settings
│  └─ Setup.py
├─ suites
│  ├─ test_reg_action_chain.py
│  └─ test_reg_js_action.py
└─ webactions
   ├─ javaScript_web_actions.py
   └─ action_chain_web_actions.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;File descriptions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;**settings/Setup.py *:&lt;/em&gt;* It contains the setup class for the entire test suite. All test demos share this setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;**suites/test_reg_action_chain.py *:&lt;/em&gt;* Contains the &lt;em&gt;ActionChain *test demo. When executed, it runs the test using the *ActionChain&lt;/em&gt; class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;**suites/test_reg_js_action.py *:&lt;/em&gt;* Holds the test execution class for the JavaScript web actions (execute_script).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;**webactions/javascript_web_actions.py *:&lt;/em&gt;* This file contains the web page locator and the web action classes. We import and use it inside the **suites/test_reg_js_action.py **file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;**webactions/action_chain_web_action.py *:&lt;/em&gt;* Test suite web actions and locators that use the &lt;em&gt;ActionChain&lt;/em&gt; are in this file. We import it into suites/test_reg_action_chain.py to use its class attributes and methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Test Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s the setup code for the test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — settings/Setup.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from dotenv import load_dotenv
import os
load_dotenv('.env')
LT_USERNAME = os.getenv("LT_USERNAME")
LT_ACCESS_KEY = os.getenv("LT_ACCESS_KEY")
desired_caps = {
        'LT:Options' : {
            "user" : os.getenv("LT_USERNAME"),
            "accessKey" : os.getenv("LT_ACCESS_KEY"),
            "build" : "FireTest New",
            "name" : "FireBrowser",
            "platformName" : os.getenv("test_OS")
        },
        "browserName" : "FireFox",
        "browserVersion" : "103.0",
    }
gridURL = "@hub.lambdatest.com/wd/hub"&amp;gt;https://{}:{}@hub.lambdatest.com/wd/hub".format(LT_USERNAME, LT_ACCESS_KEY)
class Setting:    
    def __init__(self):
        self.driver = webdriver.Remote(command_executor=gridURL, desired_capabilities= desired_caps)
    def setUp(self):
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
    def tearDown(self):
        if (self.driver != None):
            print("Cleaning the test environment")
            self.driver.quit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code is the &lt;em&gt;Settings&lt;/em&gt; class for the test suite. You start by importing the required libraries and loading your grid username and access key from the environment variable file using the dotenv package.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ay4mSWrLTF6bJOf_k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ay4mSWrLTF6bJOf_k.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To obtain your grid username and access key, head over to your &lt;a href="https://automation.lambdatest.com/build?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest Dashboard’s &lt;/a&gt;&lt;strong&gt;Builds&lt;/strong&gt; directory. Click the &lt;strong&gt;Access Key&lt;/strong&gt; button at the top right to reveal your grid details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A91DW-Z9owXsbEjqj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A91DW-Z9owXsbEjqj.jpg" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This detailed guide explains how to detect &lt;a href="https://www.lambdatest.com/learning-hub/flaky-test?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;flaky tests&lt;/a&gt;, its causes, strategies to reduce flakiness and much more.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;em&gt;Settings *class starts with the driver attribute. The driver attribute connects to the remote grid using the *webdriver.Remote&lt;/em&gt; method; this accepts the &lt;em&gt;gridURL&lt;/em&gt; variable and the desired_capabilities dictionary as the test executor and test capability settings, respectively.&lt;/p&gt;

&lt;p&gt;In this blog on press enter without WebElement in Selenium Python, we will generate the test capabilities from the &lt;a href="https://www.lambdatest.com/capabilities-generator/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest Automation Capability Generator&lt;/a&gt; as done in this test demo.&lt;/p&gt;

&lt;p&gt;We used Firefox version 103.0 as the test browser in this demo. The chosen OS platform is Windows 10 (loaded from the .env file as shown below).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Az3y1l3E71m9NMVgI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Az3y1l3E71m9NMVgI.png" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The *setUp *method pauses the driver implicitly for DOM elements to load. It then maximizes the window once it loads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ae3JodhnYrilUizOT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ae3JodhnYrilUizOT.png" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;tearDown&lt;/em&gt; method cleans up the test environment and quits the browser after each test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2008%2F0%2AHkkcE5pugZNEpeaR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2008%2F0%2AHkkcE5pugZNEpeaR.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We only need one setup file since the entire test suite shares the *Settings *class.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, I’ll start the test demonstration using Selenium’s &lt;em&gt;ActionChains&lt;/em&gt;. Then I’ll show you how to run similar test steps using the JavaScript (&lt;em&gt;execute_script)&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;So let’s get started with the demonstrations in the following sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing with Selenium’s ActionChains
&lt;/h2&gt;

&lt;p&gt;This section on press enter without WebElement in Selenium Python details the test demonstration using the &lt;em&gt;ActionChains&lt;/em&gt; class.&lt;br&gt;
We’ll start with the web actions &lt;strong&gt;&lt;em&gt;(webactions/action_chain_web_action.py)&lt;/em&gt;&lt;/strong&gt;, which we’ll then import and use inside the &lt;em&gt;ActionChains&lt;/em&gt; test runner (&lt;strong&gt;&lt;em&gt;suites/test_reg_action_chain.py&lt;/em&gt;&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s look at our test scenario before we begin:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the test website.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press the Tab key until the mouse points to the first input field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill the input fields sequentially with data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press the terms and conditions checkbox.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Submit the registration form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check for a successful registration by taking the title of the following web page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This guide focuses on &lt;a href="https://www.lambdatest.com/learning-hub/test-automation-metrics?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test automation metrics&lt;/a&gt;, its significance, strategies, challenges, and key test automation metrics for measuring success.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;FileName — webactions/action_chain_web_action.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver.common.by import By
import time
class todoLocator:
    First_Name = 'input[placeholder=\"First Name\"]'
    Last_Name = 'input[placeholder=\"Last Name\"]'
    Email = 'input[placeholder=\"E-Mail\"]'
    Phone = 'input[placeholder=\"Telephone\"]'
    Password = 'input[placeholder=\"Password\"]'
    Password_Confirm = 'input[placeholder=\"Password Confirm\"]'
    Subscribe_yes = ".//*[contains(text(), 'Yes')]"
    Agree_Yes = ".//*[contains(text(), 'I have read and agree to the')]"
    Submit_Button ='input[value=\"Continue\"]'
class registerJSWebActions(todoLocator):
    def __init__(self, driver) -&amp;gt; None:
        self.driver = driver
    def getWeb(self, URL):
        self.driver.get(URL)

    def getTitle(self):
        return self.driver.title    
    def inputfirstName(self, firstName):    
        first_name_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.First_Name)
            )    
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(firstName),
              first_name_field
        )     
    def inputlastName(self, lastName):    
        last_name_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Last_Name)
            ) 
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(lastName),
              last_name_field
        )
    def inputEmail(self, email):
        Email_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Email)
            ) 
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(email),
              Email_field
        )
    def inputPhone(self, phone):
        phone_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Phone)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(phone),
              phone_field
        )
    def inputPassword(self, password):
        password_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Password)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(password),
              password_field
        )

    def inputpasswordConfirm(self, password_confirm):
        password_confirm_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Password_Confirm)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(password_confirm),
              password_confirm_field
        )
    def subScribe(self):
        subscribebox = self.driver.find_element(By.XPATH, self.Subscribe_yes)
        return self.driver.execute_script("arguments[0].click()", subscribebox)
    def agreetoTerms(self):
        agree_field = self.driver.find_element(By.XPATH, self.Agree_Yes)
        return self.driver.execute_script("arguments[0].click()", agree_field)
    def submit(self):
        submit_button = self.driver.execute_script(
            "return document.querySelector('{}')".format(self.Submit_Button)
            )
        self.driver.execute_script("arguments[0].click()", submit_button)
        time.sleep(10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;While you’ll typically write &lt;em&gt;ActionChains&lt;/em&gt; in sequence, I separated each into methods to make it more readable, reusable, and callable while executing the test runner.&lt;/p&gt;

&lt;p&gt;Since our test needs to send data and locate elements in an action chain, we start by importing &lt;strong&gt;Keys, ActionChains&lt;/strong&gt;, and &lt;strong&gt;By&lt;/strong&gt; from Selenium.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A_6vJ7ryTbpqyF4Jl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A_6vJ7ryTbpqyF4Jl.png" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The locator class &lt;em&gt;(todoLocator)&lt;/em&gt; only defines the website header element and the terms agreement checkbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2808%2F0%2A-PC1dD6Uf3E4To8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2808%2F0%2A-PC1dD6Uf3E4To8s.png" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The registration &lt;em&gt;WebAction&lt;/em&gt; class &lt;em&gt;(registerWebActions)&lt;/em&gt; inherits the locator class to use its attributes. It then initializes with the WebDriver; we’ll derive this from the &lt;em&gt;Settings&lt;/em&gt; class while instantiating this object inside the test runner file.&lt;br&gt;
Next is the declaration of the driver and the action attributes; these are the driver and the &lt;em&gt;ActionChains&lt;/em&gt;, respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A4G5tASFI7kjOJ9O-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A4G5tASFI7kjOJ9O-.png" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next are the methods for launching the web page URL and getting its title.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACm2tt8ZlFS8Ks24x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACm2tt8ZlFS8Ks24x.png" width="742" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Learn the ins and outs of &lt;a href="https://www.lambdatest.com/learning-hub/test-execution-engine?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test execution engines&lt;/a&gt; through our extensive guide, and enhance your testing workflow with automation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The header element is easy to locate since most web pages have one. I included it in the locator earlier because I wanted to start tabbing from the header element, and the test needs to click a blank point on the header to begin tabbing from there.&lt;/p&gt;

&lt;p&gt;This allows you to count the number of times your test needs to press the Tab key to point the mouse to the first form field.&lt;/p&gt;

&lt;p&gt;Think of this as navigating a web page using your keyboard without the mouse; you might need to press the Tab key a few times to get to a particular location. We applied a similar concept to mimic a user’s interaction with a web page.&lt;/p&gt;

&lt;p&gt;In our case, the test clicks the header elements and presses the Tab Key six times before reaching the first input field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2804%2F0%2AzECsHVY_1Qv-9ubL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2804%2F0%2AzECsHVY_1Qv-9ubL.png" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll also intermittently press the Tab key once or twice in some places. So next, we define methods for pressing Tab once and twice. These are handy while executing these actions inside the test runner file &lt;strong&gt;&lt;em&gt;(suites/test_reg_action_chain.py)&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALK9Pmpix9HpXlTH0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALK9Pmpix9HpXlTH0.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we define functions for entering the user’s details into the form fields. As mentioned earlier, Selenium executes *ActionChains *sequentially. So Under the hood, each class method is a sequence of the previous one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2280%2F0%2Aong9C9PLwDCaRMDh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2280%2F0%2Aong9C9PLwDCaRMDh.png" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As for the terms and agreement checkbox — it needs a &lt;strong&gt;&lt;em&gt;click&lt;/em&gt;&lt;/strong&gt; action before you can submit a registration form — so we located that previously using its text content parameter with the &lt;em&gt;XPath&lt;/em&gt; method inside the todoLocator class. Locating a web element this way doesn’t require a CSS locator since &lt;a href="https://www.lambdatest.com/blog/complete-guide-for-using-xpath-in-selenium-with-examples/" rel="noopener noreferrer"&gt;XPath&lt;/a&gt; finds it by the specified text.&lt;/p&gt;

&lt;p&gt;However, multiple elements with the exact text content on the same web page can limit this method. But you can leverage XPath’s node (nth) feature to solve this problem.&lt;/p&gt;

&lt;p&gt;Here’s how we call an action on the agreement checkbox:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2500%2F0%2AOvG-7pihVkmKGJFS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2500%2F0%2AOvG-7pihVkmKGJFS.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Explore our comprehensive guide on &lt;a href="https://www.lambdatest.com/learning-hub/gui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;GUI Testing,&lt;/a&gt; uncovering its vital role in software development. Learn about its different types, best practices, and steps for effective implementation to enhance your software’s user interaction.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;em&gt;self.agree_yes&lt;/em&gt; attribute comes from the inherited locator class (&lt;em&gt;todoLocator&lt;/em&gt;).&lt;br&gt;
The form-filling actions end with the submit method for submitting the form. This only involves pressing the Enter key (&lt;em&gt;Keys.Enter&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ag2q4Pv1RWttFplR3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ag2q4Pv1RWttFplR3.png" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we define the action execution method (&lt;em&gt;executeactionChain&lt;/em&gt;) to perform the declared actions inside an action chain. We achieve this using &lt;em&gt;ActionChains&lt;/em&gt;’ &lt;em&gt;action.perform&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;implicitly_wait&lt;/em&gt; method is only a desired test property, not a requirement. It pauses the browser window for 10 seconds before exiting the test. You can remove it if you don’t want a pause after the test execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ASDwpOc4-86E6wvA-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ASDwpOc4-86E6wvA-.png" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — suites/test_reg_action_chain.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")
from webactions.action_chain_web_action import registerWebActions
from settings.Setup import Setting
settings = Setting()
webactions = registerWebActions(settings.driver)

class TestUserReg():
    def test_user_registration(self):
        settings.setUp()
        webactions.getWeb(  "https://ecommerce-playground.lambdatest.io/index.php?route=account/register")
        title = webactions.getTitle()
        assert "Register" in title, "Todo is not in title"
        webactions.navigatetoForm()
        webactions.inputfirstName("Idowu")
        webactions.presstabOnce()
        webactions.inputlastName("Omisola")
        webactions.presstabOnce()
        webactions.inputEmail("miniTest12@gmail.com")
        webactions.presstabOnce()
        webactions.inputPhone("08044554455")
        webactions.presstabOnce()
        webactions.inputPassword("12345678")
        webactions.presstabOnce()
        webactions.inputpasswordConfirm("12345678")
        webactions.presstabTwice()
        webactions.agreetoTerms()
        webactions.presstabTwice()
        webactions.submit()
        webactions.executeactionChain()
        settings.driver.current_url
        current_title = webactions.getTitle()
        assert "Created" in current_title, "Created is not in title"
        settings.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The code above executes the web action chains when you run the &lt;em&gt;pytest&lt;/em&gt; command via the terminal.&lt;/p&gt;

&lt;p&gt;First, we import the sys module and use this to append to the module system paths. Then we import the &lt;em&gt;registerWebActions&lt;/em&gt; class from the &lt;em&gt;action_chain_web_action.py*module. We instantiate this as *webactions&lt;/em&gt; using the driver attribute from the settings object; this allows the WebDriver to act on the test website as declared in the &lt;em&gt;ActionChains&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We also import &lt;em&gt;Setting&lt;/em&gt; from the setup module (instantiated as settings).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2592%2F0%2A4t-4-6ZDoQ6uMl2F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2592%2F0%2A4t-4-6ZDoQ6uMl2F.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;TestUserReg&lt;/em&gt; class has only one method, &lt;em&gt;test_user_registration&lt;/em&gt;, that executes the web action methods from the &lt;em&gt;registerWebActions&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;We call the &lt;em&gt;setUp&lt;/em&gt; method to set up the test environment and maximize the browser window. As a convention, the test starts by launching the test website.&lt;/p&gt;

&lt;p&gt;Then we get the web page title using the &lt;em&gt;getTitle&lt;/em&gt; method of the &lt;em&gt;webactions&lt;/em&gt; object and assert if “Register” is in the title text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AAnFGHwbqUbRgPw-l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AAnFGHwbqUbRgPw-l.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next are the test steps execution:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Our test navigates to the first form field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AICTpNJO-js7BWuor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AICTpNJO-js7BWuor.png" width="726" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Fill the form fields and press the Tab key once after filling each input field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2004%2F0%2AM6iz1hOFmwKIMUvH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2004%2F0%2AM6iz1hOFmwKIMUvH.png" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Looking to manage your tests more efficiently? In this blog, explore a variety of &lt;a href="https://www.lambdatest.com/blog/best-test-management-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test case management&lt;/a&gt; tools and select the one that suits your team’s needs.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I maintained the default subscription option, which is &lt;strong&gt;No&lt;/strong&gt;. So there was no need to click that since I didn’t want to subscribe. You might need to write methods to use the Left and Right keys within the action chain class to switch between &lt;strong&gt;Yes&lt;/strong&gt; and &lt;strong&gt;No&lt;/strong&gt; if you want your test to “Subscribe to Newsletter.”&lt;/p&gt;

&lt;p&gt;Hence, the test presses Tab twice to skip that option and jump to the “I have read and agree to the Privacy Policy” checkbox, which requires a click action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AB3sEoXu6maBZ5XAp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AB3sEoXu6maBZ5XAp.png" width="696" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; “Privacy Policy” is in a separate element. So our test presses Tab twice once more to point the mouse to the Submit button. It then presses the Enter key to submit the registration form and executes this action chain by calling the &lt;em&gt;executeactionChain&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Adub91tg9Es2xidHW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Adub91tg9Es2xidHW.png" width="772" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we get the current URL and assert if “Created” is in its title text to confirm whether or not our test successfully registered a user. Then we call the &lt;em&gt;tearDown&lt;/em&gt; method of the &lt;em&gt;Settings&lt;/em&gt; class to clean up the test environment and exit the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2440%2F0%2Aefznyz4gIyqgtBv1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2440%2F0%2Aefznyz4gIyqgtBv1.png" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution of the ActionChains
&lt;/h2&gt;

&lt;p&gt;Go to your project root directory and run the &lt;em&gt;pytest&lt;/em&gt; command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s the test execution on the command line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AP-8oBGBbaqcDAs3l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AP-8oBGBbaqcDAs3l.jpg" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our test also runs successfully on the cloud grid as shown below. Here we are using a cloud grid offered by the LambdaTest platform.&lt;/p&gt;

&lt;p&gt;LambdaTest is a digital experience testing platform that enables developers and QA engineers to perform &lt;a href="https://www.lambdatest.com/selenium-python-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium Python testing&lt;/a&gt; on over 3000+ real browsers and OS combinations. LambdaTest provides support for different &lt;a href="https://www.lambdatest.com/blog/top-python-frameworks-for-automation/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Python testing frameworks&lt;/a&gt; to &lt;a href="https://www.lambdatest.com/python-automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Python automation testing&lt;/a&gt;. In addition, you can parallelize your test execution to expedite software release cycles.&lt;/p&gt;

&lt;p&gt;Visit our documentation to &lt;a href="https://www.lambdatest.com/support/docs/python-with-selenium-running-python-automation-scripts-on-lambdatest-selenium-grid/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=support_doc" rel="noopener noreferrer"&gt;get started with Selenium Python testing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A5hk7VkaKKw5QrnLs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A5hk7VkaKKw5QrnLs.jpg" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Selenium’s JavaScript Executor (execute_script)
&lt;/h2&gt;

&lt;p&gt;In this section of this blog on press enter without WebElement in Selenium Python, now let’s see how to navigate the same web page using JavaScript embedding (&lt;em&gt;execute_script&lt;/em&gt; method).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s start with our test scenario&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the registration page (test website).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill in the registration form fields using JavaScript actions (&lt;em&gt;execute_script&lt;/em&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the terms and agreement checkbox using JavaScript’s click event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the submit button using JavaScript’s click event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Take the title on the following page to check for successful registration.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;FileName — webactions/javaScript_web_actions.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver.common.by import By
import time
class todoLocator:
    First_Name = 'input[placeholder=\"First Name\"]'
    Last_Name = 'input[placeholder=\"Last Name\"]'
    Email = 'input[placeholder=\"E-Mail\"]'
    Phone = 'input[placeholder=\"Telephone\"]'
    Password = 'input[placeholder=\"Password\"]'
    Password_Confirm = 'input[placeholder=\"Password Confirm\"]'
    Subscribe_yes = ".//*[contains(text(), 'Yes')]"
    Agree_Yes = ".//*[contains(text(), 'I have read and agree to the')]"
    Submit_Button ='input[value=\"Continue\"]'
class registerJSWebActions(todoLocator):
    def __init__(self, driver) -&amp;gt; None:
        self.driver = driver
    def getWeb(self, URL):
        self.driver.get(URL)

    def getTitle(self):
        return self.driver.title    
    def inputfirstName(self, firstName):    
        first_name_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.First_Name)
            )    
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(firstName),
              first_name_field
        )     
    def inputlastName(self, lastName):    
        last_name_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Last_Name)
            ) 
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(lastName),
              last_name_field
        )
    def inputEmail(self, email):
        Email_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Email)
            ) 
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(email),
              Email_field
        )
    def inputPhone(self, phone):
        phone_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Phone)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(phone),
              phone_field
        )
    def inputPassword(self, password):
        password_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Password)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(password),
              password_field
        )

    def inputpasswordConfirm(self, password_confirm):
        password_confirm_field = self.driver.execute_script(
            "return document.querySelector('{}');".format(self.Password_Confirm)
            )
        return self.driver.execute_script(
            "arguments[0].value='{}';".format(password_confirm),
              password_confirm_field
        )
    def subScribe(self):
        subscribebox = self.driver.find_element(By.XPATH, self.Subscribe_yes)
        return self.driver.execute_script("arguments[0].click()", subscribebox)
    def agreetoTerms(self):
        agree_field = self.driver.find_element(By.XPATH, self.Agree_Yes)
        return self.driver.execute_script("arguments[0].click()", agree_field)
    def submit(self):
        submit_button = self.driver.execute_script(
            "return document.querySelector('{}')".format(self.Submit_Button)
            )
        self.driver.execute_script("arguments[0].click()", submit_button)
        time.sleep(10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The ultimate guide to &lt;a href="https://www.lambdatest.com/learning-hub/software-testing-metrics?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;software testing metrics&lt;/a&gt;: definition, types, and examples explained for informed decisions. Enhance your testing process now!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above code defines the web actions for JavaScript embedding demonstration. It starts with the &lt;em&gt;todoLocator&lt;/em&gt; class, whose attributes are the web element locators. However, these locators don’t require web element inspection, as they’re visibly definitive.&lt;/p&gt;

&lt;p&gt;Although we don’t know the underlying DOM structure, we know they’re input fields with placeholders.&lt;/p&gt;

&lt;p&gt;Thankfully, we can get these input elements using their placeholders with JavaScript’s &lt;em&gt;querySelector&lt;/em&gt;. You’ll see how that works down the line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2560%2F0%2AvrNXPW8h71ph6hE0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2560%2F0%2AvrNXPW8h71ph6hE0.png" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We trace the “Subscribe” option and the terms checkbox by their peculiar text content using the &lt;em&gt;XPath&lt;/em&gt; method since we’ve assumed that we don’t know anything about their elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2684%2F0%2Ax2bj8ZLAeWShaLbG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2684%2F0%2Ax2bj8ZLAeWShaLbG.png" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the Submit input, I wasn’t sure at first whether it was a button or an input tag. But it works with the input tag. So sticking to locating an input with a text that says, “Continue” using XPath works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZk8dQq2UPcaoaGSs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZk8dQq2UPcaoaGSs.png" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we did earlier for the &lt;em&gt;ActionChains&lt;/em&gt;, the &lt;em&gt;registerJSWebActions&lt;/em&gt; class inherits the &lt;em&gt;todoLocators&lt;/em&gt; class and its attributes and initializes with the WebDriver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Av2z_UpOC_1B6sSsh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Av2z_UpOC_1B6sSsh.png" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned, we’ll use JavaScript’s &lt;em&gt;querySelector&lt;/em&gt; to pick on web elements rather than CSS Selector.&lt;/p&gt;

&lt;p&gt;This takes the following form:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.querySelector(element)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Thus, a typical input field as used in our test looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2748%2F0%2ATSSEgEjaJ93LTiTd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2748%2F0%2ATSSEgEjaJ93LTiTd.png" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first_name_field variable defines the First Name input element grabbed using the &lt;em&gt;querySelector&lt;/em&gt;. Since the embedded JavaScript is a string, we insert the First_Name attribute (inherited from &lt;em&gt;todoLocator&lt;/em&gt; class) using Python’s string &lt;em&gt;format&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;The returned code line within this method uses JavaScript to write the required data (&lt;em&gt;firstName&lt;/em&gt;) into the form field accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A7c58lzI866DlBfnM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2100%2F0%2A7c58lzI866DlBfnM.png" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the convention for the other input actions.&lt;/p&gt;

&lt;p&gt;However, the &lt;em&gt;subscribe&lt;/em&gt; and &lt;em&gt;agreetoTerms&lt;/em&gt; methods use XPath to locate web elements based on specified text content. These require click action. So JavaScript does that for us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2900%2F0%2Aj9g1skpe_IafcUmT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2900%2F0%2Aj9g1skpe_IafcUmT.png" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the test locates the Submit input button using the &lt;em&gt;querySelector&lt;/em&gt; and submits the registration form using JavaScript’s click action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2808%2F0%2A_tacCQiH_ZU5uPrZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2808%2F0%2A_tacCQiH_ZU5uPrZ.png" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName-suites/test_reg_js_with_actions.py&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")
from webactions.javaScript_web_actions import registerJSWebActions
from settings.Setup import Setting
settings = Setting()
webactions = registerJSWebActions(settings.driver)
class TestUserRegWithJS():
    def test_user_registration_js(self):
        settings.setUp()
        webactions.getWeb(     "https://ecommerce-playground.lambdatest.io/index.php?route=account/register")
        title = webactions.getTitle()
        assert "Register" in title, "Todo is not in title"
        webactions.inputfirstName("Idowu")
        webactions.inputlastName("Omisola")
        webactions.inputEmail("Iminsshjsyytdsas@gmail.com")
        webactions.inputPhone("08044554455")
        webactions.inputPassword("12345678")
        webactions.inputpasswordConfirm("12345678")
        webactions.subScribe()
        webactions.agreetoTerms()
        webactions.submit()
        settings.driver.current_url
        current_title = webactions.getTitle()
        assert "Created" in current_title, "Created is not in title"
        settings.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code executes the JavaScript web actions written earlier. First, we import the registerJSWebActions and Setting from their respective modules.&lt;/p&gt;

&lt;p&gt;We then instantiate the &lt;em&gt;Setting&lt;/em&gt; class as &lt;em&gt;settings&lt;/em&gt;. We instantiate the r*egisterJSWebActions* class as &lt;em&gt;WebActions&lt;/em&gt; using the driver attribute from the &lt;em&gt;settings&lt;/em&gt; object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2624%2F0%2AL-iY6OWWWsJ6PrOa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2624%2F0%2AL-iY6OWWWsJ6PrOa.png" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;TestUserRegWithJS&lt;/em&gt; class holds the test execution method (&lt;em&gt;test_user_registration_js&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; This starts with the test setup, website launching, and title grab with an assertion to check if the browser agent has loaded the test website successfully.&lt;/p&gt;

&lt;p&gt;This is similar to the action chain option code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AGotx_bBZ2IEb41ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AGotx_bBZ2IEb41ei.png" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Next, we call the input actions as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2AltjHOfagiHpFS4TB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2AltjHOfagiHpFS4TB.png" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Click the Subscribe and Terms agreement buttons:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkQSdFQe3ADYHmyTJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkQSdFQe3ADYHmyTJ.png" width="680" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Finally, click the Submit button, get the next page title, and assert whether or not the test registered the user successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2440%2F0%2AbsBmv4hVsKE8TTWV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2440%2F0%2AbsBmv4hVsKE8TTWV.png" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Quit the browser and end the test by calling the &lt;em&gt;tearDown&lt;/em&gt; method from the &lt;em&gt;Setting&lt;/em&gt; class:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A3TB4z2TuQU5CuFp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A3TB4z2TuQU5CuFp7.png" width="588" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript (execute_script) Demo Execution
&lt;/h2&gt;

&lt;p&gt;To execute the JavaScript demonstration for navigating the web without an element, cd into your project root folder from the command line and run the &lt;em&gt;pytest&lt;/em&gt; command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Provided the registered email address is unique, the test runs successfully, as seen via the command line:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AemQEbcdHNBRvqwtH.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AemQEbcdHNBRvqwtH.jpg" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our demo also runs successfully on the cloud grid, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AcQvkvDnH-Vvpe_YW.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AcQvkvDnH-Vvpe_YW.jpg" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Deep dive to learn about test automation, its uasage, types and also gain insights on how to get started with &lt;a href="https://www.lambdatest.com/learning-hub/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;automated testing&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  You can get creative with your automation testing
&lt;/h2&gt;

&lt;p&gt;No cap fits it all when navigating a web page without specifying elements. While the options we’ve considered may save time in some cases, they could also be daunting for testing complex websites or executing &lt;a href="https://www.lambdatest.com/learning-hub/end-to-end-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=jul_27&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;end-to-end testing.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If web elements are available, testing a website without inspecting its DOM for CSS Selectors isn’t a best practice. It could be costly, time-consuming, and confusing. However, such a situation might cross your way as a tester. Improvise your way with the test website — regardless of the odds.&lt;/p&gt;

&lt;p&gt;As you’ve seen in our test demos, the &lt;em&gt;ActionChains&lt;/em&gt; class and the &lt;em&gt;execute_script&lt;/em&gt; methods are handy to navigate a website and press enter without WebElement in Selenium Python.&lt;/p&gt;

&lt;p&gt;We had to go through some logical trials to navigate the test web page and complete the automation testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the command for Enter text in Selenium?
&lt;/h3&gt;

&lt;p&gt;In Selenium, the command for entering text into an input field is the &lt;em&gt;send_keys()&lt;/em&gt; method. Here’s an example of how to use it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element = driver.find_element_by_id("myInput")
element.send_keys("Hello, World!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, driver refers to the WebDriver instance, and &lt;em&gt;find_element_by_id(“myInput”)&lt;/em&gt; is used to locate the input field element on the webpage. The &lt;em&gt;send_keys()&lt;/em&gt; method is then called on the element to enter the desired text, which in this case is “Hello, World!”.&lt;/p&gt;

&lt;p&gt;You can replace “&lt;em&gt;myInput&lt;/em&gt;” with the appropriate locator method (find_element_by_name, find_element_by_xpath, &lt;em&gt;find_element_by_css_selector&lt;/em&gt;, etc.) based on how you want to locate the element.&lt;/p&gt;

&lt;p&gt;After using &lt;em&gt;send_keys()&lt;/em&gt; to enter the text, you can interact with other elements or simulate additional actions as needed.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>opensource</category>
      <category>selenium</category>
    </item>
    <item>
      <title>How To Check If An Element Exists In Python Selenium</title>
      <dc:creator>Idowu Omisola</dc:creator>
      <pubDate>Fri, 03 Nov 2023 07:33:25 +0000</pubDate>
      <link>https://dev.to/testmuai/how-to-check-if-an-element-exists-in-python-selenium-3afb</link>
      <guid>https://dev.to/testmuai/how-to-check-if-an-element-exists-in-python-selenium-3afb</guid>
      <description>&lt;p&gt;The content of a dynamic web page is changeable, which can change with each request or session as the database is updated. This can lead to automation test failures when using tools like &lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;. These changes alter the DOM layouts and the attributes of web elements, making it difficult for automation scripts to locate specific elements based on their previous specifications.&lt;/p&gt;

&lt;p&gt;Selenium’s built-in mechanisms, such as &lt;em&gt;NoSuchElementException&lt;/em&gt;, are not always sufficient to handle these dynamic changes, and they may not account for delays caused by asynchronous calls or network issues.&lt;/p&gt;

&lt;p&gt;To address this challenge to check if an element exists in &lt;a href="https://www.lambdatest.com/learning-hub/python-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Python Selenium&lt;/a&gt; while locating web elements, you can implement a solution that fits if an element exists before interacting with it. This approach helps in tracking and adapting to changes in the DOM content.&lt;/p&gt;

&lt;p&gt;While Selenium’s *NoSuchElementException *can be used for this purpose, it may need more flexibility and specificity. A more effective solution would involve creating custom methods or functions that consider checking if an element exists in Python Selenium, adapting to changes, and handling potential delays due to asynchronous calls or network glitches. This ensures more robust and adaptable automation tests on dynamic web pages.&lt;/p&gt;

&lt;p&gt;In this blog, we will delve into the essential skill of checking if an element exists in Python Selenium during &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt;. We will cover the significance of this skill and provide a step-by-step guide on how to implement custom methods and functions to accomplish this task effectively.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.lambdatest.com/free-online-tools/binary-to-decimal?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;Binary to Decimal&lt;/a&gt; Converter is a tool that converts binary numbers into their equivalent decimal form. Simply enter a binary number and let this converter do it for you.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why check if an element exists in Python Selenium?
&lt;/h2&gt;

&lt;p&gt;When your &lt;a href="https://www.lambdatest.com/automated-ui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;UI automation test&lt;/a&gt; encounters a failure, a crucial strategy is to validate if the targetted web elements are present and ready for interaction. However, a more effective and sustainable approach involves checks right from the start rather than relying on debugging when issues arise.&lt;/p&gt;

&lt;p&gt;By involving these checks in the initial stages, you can proactively deal with potential errors and set a strong foundation for reliable automation testing.&lt;/p&gt;

&lt;p&gt;In this section, we will delve into the significance of this proactive approach, exploring why it’s essential and how to implement it effectively. This strategy ensures smoother and more robust testing experiences, ultimately saving time and resources in the long run.&lt;/p&gt;

&lt;p&gt;Here are some reasons to check if an element exists in Python Selenium during &lt;a href="https://www.lambdatest.com/learning-hub/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test automation&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Handling dynamic web content&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Handling dynamic web content in automation testing is a crucial skill. When web pages change frequently or elements get reshuffled in the Document Object Model(DOM) layout, causing the automation tests to break, this is even common while automating shadow web elements.&lt;/p&gt;

&lt;p&gt;To address this, testers use various strategies like switching to relative XPath locators, locating the web elements with multiple attributes, or finding elements by their indexes.&lt;/p&gt;

&lt;p&gt;Other locators like ID, className, CSSSelector, and more can come in handy based on situations and needs when locating a web element to check if an element exists in Python Selenium.&lt;/p&gt;

&lt;p&gt;Explore this comprehensive blog on Selenium locators to enhance your element identification skills. This blog provides valuable insights, tips, and best practices to help you become a pro at locating web elements.&lt;/p&gt;

&lt;p&gt;By proactively checking if an element exists in Python Selenium and element visibility, testers can adapt their tests to handle these changes, making their automation more robust and reliable.&lt;/p&gt;

&lt;p&gt;This approach helps with smoother testing experiences and prevents potential bugs from leaking into production. Handling dynamic web content is essential for successful automation testing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Early bug detection&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides web content dynamism, a web element may be present, but it can be slow to respond inactive due to external conditions like network speed.&lt;/p&gt;

&lt;p&gt;Checking if an element exists in Python Selenium during test automation helps you identify the direct cause of a test failure. It prevents potential bugs from leaking into production.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A tool that converts &lt;a href="https://www.lambdatest.com/free-online-tools/decimal-to-octal?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;decimal to octal&lt;/a&gt; representation. Input a decimal number and click ‘Convert to Octal’ to get the result in seconds!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduce &lt;a href="https://www.lambdatest.com/learning-hub/flaky-test?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test flakiness&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a desired web element is not rendering correctly or missing, it might indicate a bug in the UI or the &lt;a href="https://www.lambdatest.com/learning-hub/test-suite?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test suite&lt;/a&gt;. Checking the presence and visibility of the desired web element helps identify where updates may be needed in either the UI or the test suite.&lt;/p&gt;

&lt;p&gt;It helps verify that a web element is visible and responsive to user interactions before moving to further test steps. It also helps verify if your UI test needs to include a significant action. This might involve ensuring the target web element exists and is visible before any interaction is performed.&lt;/p&gt;

&lt;p&gt;To overcome flaky tests and unexpected failures, explore this blog on &lt;a href="https://www.lambdatest.com/blog/auto-healing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;how to overcome flaky tests and unexpected failures&lt;/a&gt;. This resource provides valuable insights and strategies to enhance the reliability of your test automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different techniques for checking if an element exists in Python Selenium
&lt;/h2&gt;

&lt;p&gt;Techniques like counting the presence of the target element, utilizing boolean assertions along with &lt;em&gt;expected_conditions&lt;/em&gt;, or using Selenium’s built-in exception handling can be a great help while checking if an element exists in Python Selenium.&lt;/p&gt;

&lt;p&gt;Handling exceptions in Selenium can sometimes be tricky and challenging when dealing with concepts like dynamic web elements. To know more about what types of built-in exceptions Selenium provides, explore this blog on &lt;a href="https://www.lambdatest.com/blog/handling-errors-and-exceptions-in-selenium-python/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;how to handle errors and exceptions in Selenium Python&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the further section, we will see examples demonstrating the different techniques to check if an element exists in Python Selenium using the &lt;em&gt;count() method&lt;/em&gt; and &lt;em&gt;is_displayed, is_enabled&lt;/em&gt; with &lt;a href="https://www.lambdatest.com/blog/expected-conditions-in-selenium-examples/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;*expected_conditions&lt;/a&gt;*.&lt;/p&gt;

&lt;p&gt;Before jumping to the demonstration, let’s look into the prerequisites we need to set up, from choosing the coding language testing framework to finalizing the IDE.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Need to convert your hexadecimal code to binary quickly? Our &lt;a href="https://www.lambdatest.com/free-online-tools/hex-to-binary?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;hex to binary&lt;/a&gt; converter makes it simple, fast, and free.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this case, I will use Python version 3.10.6, and the IDE will be VS Code. You’ll also need to install the following packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;pytest&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selenium&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python-dotenv&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run our tests, we will use pytest as a test runner and Selenium as the framework that provides drivers and interactive methods to automate the test.&lt;/p&gt;

&lt;p&gt;Now, create a file and name it requirements.txt. This file must be made under your project root folder as shown:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filename: *requirements.txt&lt;/strong&gt;*&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
selenium&amp;gt;=4.6.0
python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, to install the dependencies, run the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2580%2F0%2AmDNLpN_HH7kVpD6o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2580%2F0%2AmDNLpN_HH7kVpD6o.jpg" width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These dependencies get installed into the text file you created, that is, requirement.txt&lt;/p&gt;

&lt;p&gt;In this case, we will use the dotenv package to mask secret variables, including your grid username and access key.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Using the pytest framework for running Python-based automation?&lt;/em&gt; Check out our blog on &lt;a href="https://www.lambdatest.com/learning-hub/pytest-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;pytest tutorial&lt;/a&gt;. Run your test suites in parallel across multiple browsers and operating systems for complete &lt;a href="https://www.lambdatest.com/learning-hub/test-coverage?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test coverage&lt;/a&gt;.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_CJ-vJFnAWQ"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Subscribe to the &lt;a href="https://www.youtube.com/c/LambdaTest?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=youtube" rel="noopener noreferrer"&gt;LambdaTest YouTube channel&lt;/a&gt; for more videos on &lt;a href="https://www.lambdatest.com/blog/what-is-parallel-testing-and-why-to-adopt-it/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Parallel testing&lt;/a&gt; and &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt; and to enhance your testing experience!&lt;/p&gt;

&lt;p&gt;Now that everything is set up, let’s look into the technique.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Need to convert &lt;a href="https://www.lambdatest.com/free-online-tools/csv-to-json?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;CSV to JSON&lt;/a&gt;? Try our free CSV to JSON converter tool to convert your CSV files to JSON format. Simple and easy to use. Try it now for free!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using the count() technique
&lt;/h2&gt;

&lt;p&gt;In this technique, we add the desired web element to a random list using a list-supported Selenium selector. Then, we count how many web elements are in that list. The resulting list remains empty if the web element is absent in the DOM.&lt;/p&gt;

&lt;p&gt;In the following example, we’ll test a selection action from a dropdown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Select action from drop-down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Action:&lt;/strong&gt; First, we will check if an element exists in the dropdown before taking the action. We will check if the test has selected the expected option.&lt;/p&gt;

&lt;p&gt;But before performing the action, we need to identify the element like ID or XPath that can help us interact with the UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Locating element using ID&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will perform actions on the Select Options box present on the LambdaTest Demo site using Python Selenium in this example.&lt;/p&gt;

&lt;p&gt;But before performing any action on the Select Options button, we must find the element using any locator. In this case, I will use IDs as IDs are considered unique.&lt;br&gt;
So, let’s find the element ID in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit the LambdaTest &lt;a href="https://www.lambdatest.com/selenium-playground/select-dropdown-demo?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Dropdown demo site&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A9SNm7QIrLVojeN4J.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A9SNm7QIrLVojeN4J.png" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click on the web page and click on Inspect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AI2hx6_RL9TwyyG_g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AI2hx6_RL9TwyyG_g.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The developer panel will appear. Now, hover over the Select Options box and get its ID.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AXiLfLSNTnDTy9X1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AXiLfLSNTnDTy9X1h.png" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The ID of the Select Options box is &lt;em&gt;select-demo&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Great, now that you have the element ID, let’s proceed with the other actions, like importing Selenium file libraries, invoking Chrome Driver, maximizing the browser, and more in our &lt;a href="https://www.lambdatest.com/learning-hub/test-scripts?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test script&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select



driver = webdriver.Chrome()

class TestSelection():


    def should_select_text(self):
        drop_down_button = "select-demo"
        selected_value = "selected-value"
        url = "https://www.lambdatest.com/selenium-playground/select-dropdown-demo"
        driver.maximize_window()
        driver.get(url)
        elements = driver.find_elements(By.ID, drop_down_button)
        assert len(elements)&amp;gt;0, "The element does not exist"
        drop_down = Select(driver.find_element(By.ID, drop_down_button))
        selected = driver.find_element(By.CLASS_NAME, selected_value)
        drop_down.select_by_visible_text("Sunday")

        assert "Sunday" in selected.text, "The expected day not selected"
        print(selected.text)
        driver.quit()

should_select_text_from_dropdown = TestSelection()

should_select_text_from_dropdown.should_select_text()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Great, now that you have the element ID, let’s proceed with the other actions, like importing Selenium file libraries, invoking Chrome Driver, maximizing the browser, and more in our &lt;a href="https://www.lambdatest.com/learning-hub/test-scripts" rel="noopener noreferrer"&gt;test script&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Looking to convert binary to hex? Convert binary numbers to hex with ease using our free online &lt;a href="https://www.lambdatest.com/free-online-tools/binary-to-hex?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;Binary to Hex&lt;/a&gt; Converter tool. Perfect for developers and coders.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we see the outcome, let us understand the code in the following steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import statements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Importing all necessary Selenium libraries and related modules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4jJbRAj1x_xyj8IQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4jJbRAj1x_xyj8IQ.png" width="800" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a *WebDriver *instance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This line initializes a new instance of the Chrome WebDriver, which will be used for automation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkhAZVkP103OK4D3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkhAZVkP103OK4D3t.png" width="504" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defining a test class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code defines a Python class named *TestSelection *to encapsulate the test methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Af8YXGpRE7Gv_gbu7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Af8YXGpRE7Gv_gbu7.png" width="382" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test method *should_select_text&lt;/strong&gt;*&lt;/p&gt;

&lt;p&gt;This method is defined within the TestSelection class. It performs the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assigning element identifiers:&lt;/strong&gt; These variables store the IDs of the dropdown element and the selected value element on a web page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEo_Kyc9IlIMv7n7O.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEo_Kyc9IlIMv7n7O.png" width="577" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setting the URL:&lt;/strong&gt; The web page URL to be tested is stored in the URL variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApCE4yccNlaTE8lYj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApCE4yccNlaTE8lYj.png" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maximizing the browser window&lt;/strong&gt;: This command maximizes the browser window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdfDElNFV_wUUf9rK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdfDElNFV_wUUf9rK.png" width="448" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opening the web page:&lt;/strong&gt; The WebDriver navigates to the specified URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2As5bzn_D2tQsB2q4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2As5bzn_D2tQsB2q4u.png" width="356" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Locating the dropdown element:&lt;/strong&gt; It attempts to locate elements on the web page using the &lt;em&gt;By.ID&lt;/em&gt; method. If any element with the specified ID is found, it is stored in the elements variable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADejtuMiwa2hkeSwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADejtuMiwa2hkeSwr.png" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assertion for element existence:&lt;/strong&gt; This line checks if the *elements *list is not empty, indicating that the dropdown element exists on the page. If the element is not found, it raises an assertion error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ABRDWyX3OAHwiJaJC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ABRDWyX3OAHwiJaJC.png" width="796" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interacting with the dropdown:&lt;/strong&gt; The code locates the dropdown element using &lt;em&gt;driver.find_element&lt;/em&gt; and creates a &lt;em&gt;Select&lt;/em&gt; object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZ4c6K215z7XP_02r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZ4c6K215z7XP_02r.png" width="800" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Locating the selected value element:&lt;/strong&gt; The code locates the element displaying the desired value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADbwdBlwQ3Zx4tzzX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADbwdBlwQ3Zx4tzzX.png" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selecting an option from the dropdown:&lt;/strong&gt; It selects Sunday from the dropdown using the &lt;em&gt;select_by_visible_text method.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A1L2N1fujTQ3LzxPw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A1L2N1fujTQ3LzxPw.png" width="717" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assertion for selected value:&lt;/strong&gt; This line verifies that the selected text matches “Sunday” and raises an assertion error if it does not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIS7uQZQKtgH3gYOk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIS7uQZQKtgH3gYOk.png" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Printing the selected text:&lt;/strong&gt; Finally, the code prints the selected day to the console.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A2zL2fwzrVnXkF0lv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A2zL2fwzrVnXkF0lv.png" width="555" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quitting the &lt;em&gt;WebDriver&lt;/em&gt;:&lt;/strong&gt; The *WebDriver *is closed to end the automation session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AINdFWr_N3pecTjIQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AINdFWr_N3pecTjIQ.png" width="466" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating an instance of the test class and executing the test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An instance of the &lt;em&gt;TestSelection&lt;/em&gt; class is made, and the &lt;em&gt;should_select_text method&lt;/em&gt; is called to execute the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOqftaJyzAqZXdC0W.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOqftaJyzAqZXdC0W.png" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize the code, it conducts UI automation, selecting a day from a web page’s dropdown, verifying the selected value, and displaying it in the console. Additionally, it includes error handling through assertions and checking if an element exists in Python Selenium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2646%2F0%2APTRARizkxBNGxSgU.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2646%2F0%2APTRARizkxBNGxSgU.jpg" width="800" height="38"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s look into the other technique, which can make checking if an element exists in Python Selenium easier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Convert your JSON files to CSV format in seconds with our easy-to-use &lt;a href="https://www.lambdatest.com/free-online-tools/json-to-csv?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;JSON to CSV&lt;/a&gt; Converter. It’s fast, reliable, and user-friendly, making data conversion simple.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using is_displayed() and is_enabled() with expected_conditions
&lt;/h2&gt;

&lt;p&gt;Before we see how we can use &lt;em&gt;is_displayed&lt;/em&gt; and &lt;em&gt;is_enabled&lt;/em&gt; with &lt;em&gt;expected_conditions&lt;/em&gt;, we will first understand the basics of &lt;em&gt;is_displayed&lt;/em&gt; and &lt;em&gt;is_enabled&lt;/em&gt; methods in Selenium.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Is_displayed():&lt;/em&gt; The &lt;em&gt;is_displayed()&lt;/em&gt; method checks if an element on a web page is visible to the user. If the element is visual, it returns true; else, it returns false.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Is_enabled():&lt;/em&gt; The &lt;em&gt;is_enabled()&lt;/em&gt; method checks if the element is interactable. If the element is not interactable, it returns false; else, it returns true.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When automation scripts fail due to an element not being clickable or if the element is hidden behind another element, using *is_displayed() *can be helpful. Learn more on &lt;a href="https://www.lambdatest.com/blog/isdisplayed-in-selenium/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;how to use *isDisplayed() *in Selenium WebDriver.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a good glance at the &lt;em&gt;is_displayed() *and *is_enabled()&lt;/em&gt; methods, let’s understand what *expected_conditions *are.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;expected_conditions:&lt;/em&gt; In Selenium, &lt;em&gt;expected_conditions *provides methods to check various pointers of web elements such as presence, visibility, activeness, and clickability. It means you can use *expected_conditions&lt;/em&gt; to wait for a web element to be visible or active before the user can interact.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, using expected_conditions is an add-on to your element validation by verifying if the web element is available for interaction using the is_displayed and is_enabled methods. These methods return a Boolean value, which helps to ensure that the web element is ready for interaction.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;element = driver.find_element_by_name("sub_activate")
print element.is_enabled()
print(element.is_displayed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is an alternative method called custom error message, which you can use instead of expected_conditions. This custom error message allows you to manage missing elements by printing them when they are not found.&lt;/p&gt;

&lt;p&gt;Let’s understand this custom error message better with an example. We will consider the previous example using these methods:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException

driver = webdriver.Chrome()

class TestSelection():
    def should_select_text(self):

        drop_down_button = "select-demo"
        selected_value = "selected-value"
        url = "https://www.lambdatest.com/selenium-playground/select-dropdown-demo"

        driver.implicitly_wait(10)
        driver.maximize_window()
        driver.get(url)

        element_present = False
        try:
            target_element = driver.find_element(By.ID, drop_down_button)
            element_present = EC.presence_of_element_located((By.ID, drop_down_button))(driver)
        except:
            pass
        assert element_present, "element not found"

        assert target_element.is_displayed(), "The element is not visible"
        assert target_element.is_enabled(), "Element is visible but disabled"

        drop_down = Select(target_element)
        selected = driver.find_element(By.CLASS_NAME, selected_value)
        drop_down.select_by_visible_text("Sunday")

        assert "Sunday" in selected.text, "The expected day not selected"
        print(f"selected text: {selected.text}, Test status: Passed")       
        driver.quit()

should_select_text_from_dropdown = TestSelection()

should_select_text_from_dropdown.should_select_text()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import statements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Importing all necessary Selenium libraries and related modules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AODkEZLAYp_-cjxjA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AODkEZLAYp_-cjxjA.png" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a *WebDriver *instance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This line initializes a new instance of the Chrome WebDriver, which will be used for automation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjAiEkJaxF5W47GTv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjAiEkJaxF5W47GTv.png" width="504" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defining a test class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code defines a Python class named &lt;em&gt;TestSelection&lt;/em&gt; to encapsulate the test methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A2ADnunL6OsuEz5Ul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A2ADnunL6OsuEz5Ul.png" width="382" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test method *should_select_text&lt;/strong&gt;*&lt;/p&gt;

&lt;p&gt;This method is defined within the &lt;em&gt;TestSelection&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AfXU28veL2Iq-O-PS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AfXU28veL2Iq-O-PS.png" width="557" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web element IDs and URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web element IDs and the web page URL to be tested are defined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATKdVknIx2JCI_H2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATKdVknIx2JCI_H2x.png" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Driver configuration and navigation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The driver is configured with a 10-second implicit wait, the browser window is maximized, and the web page is loaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZe-Z9ChFy3Qqw05a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZe-Z9ChFy3Qqw05a.png" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, I have used implicit wait, the default wait function provided by Selenium. Implicit wait methods are applied globally; you can add this once in your code, and it applies to all the web elements specified within a script throughout the entire WebDriver instance. To know more about Selenium waits, explore this blog on &lt;a href="https://www.lambdatest.com/blog/types-of-waits-in-selenium/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;types of waits in Selenium&lt;/a&gt;, get valuable insights on holds, and learn how and when to use them.&lt;br&gt;
Check for element presence&lt;/p&gt;

&lt;p&gt;In this code section, we will check if an element exists in Python Selenium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check for element presence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this code section, we will check if an element exists in Python Selenium.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACC5FI9YKBclf8LRE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ACC5FI9YKBclf8LRE.png" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A variable element_present is initialized as false.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code attempts to find the &lt;em&gt;target_element&lt;/em&gt; using its ID and checks its presence using &lt;em&gt;expected_conditions&lt;/em&gt;. Any &lt;em&gt;NoSuchElementException&lt;/em&gt; exceptions are handled in a &lt;em&gt;try-except&lt;/em&gt; block.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARiXQ352pvlQQP7s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARiXQ352pvlQQP7s4.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use our &lt;a href="https://www.lambdatest.com/free-online-tools/random-string-generator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;random string generator&lt;/a&gt; to create random strings of any length and character set. Input the length of string and get multiple random strings in seconds!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Assert element presence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An assertion is made to verify the existence of the &lt;em&gt;target_element&lt;/em&gt;, and a custom error message is displayed if it’s not found.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKybijcnEGhmo1T-M.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKybijcnEGhmo1T-M.png" width="641" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check visibility and enablement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assertions are made to check if the target_element is displayed and enabled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_l7bQuk-XDkEwQAm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_l7bQuk-XDkEwQAm.png" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dropdown selection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this code section, we will select the dropdown option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AYwLHKAt4MHQ-kP5N.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AYwLHKAt4MHQ-kP5N.png" width="720" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;em&gt;Select&lt;/em&gt; object is created for the &lt;em&gt;target_element&lt;/em&gt; to work with dropdowns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;selected&lt;/em&gt; element is found using its class name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The “Sunday” option is selected from the dropdown.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Assert selected value&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;assert Sunday is &lt;em&gt;selected.text&lt;/em&gt;. The expected day is not selected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7BQdrwc5G4GTzqPD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7BQdrwc5G4GTzqPD.png" width="777" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An assertion is made to ensure that “Sunday” is in the selected element’s text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Print results and quit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The selected text and a Test status: &lt;em&gt;Passed&lt;/em&gt; message are printed. The &lt;em&gt;WebDriver&lt;/em&gt; instance is quit to end the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AfOc_owOR_XHXbC7T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AfOc_owOR_XHXbC7T.png" width="775" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You get the following command-line output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2966%2F0%2AOdFGvN2TOqrisSVT.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2966%2F0%2AOdFGvN2TOqrisSVT.jpg" width="800" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If true, the &lt;em&gt;target_element&lt;/em&gt; satisfies all conditions. Hence, the test runs and passes as shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2654%2F0%2AENwBgySUiVE89A6V.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2654%2F0%2AENwBgySUiVE89A6V.jpg" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use our free online &lt;a href="https://www.lambdatest.com/free-online-tools/random-word-generator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;Random Word Generator&lt;/a&gt; tool to create unique and random list of words with a click. Just input the words limit and let our tool do the rest.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using Selenium’s built-in exception
&lt;/h2&gt;

&lt;p&gt;The Selenium built-in exception catches a missing element error during automation &lt;a href="https://www.lambdatest.com/learning-hub/test-execution?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test execution&lt;/a&gt;. This approach involves the use of the &lt;em&gt;NoSuchElementException *exception class of Selenium.&lt;br&gt;
If the test code in the try block fails, Selenium executes the exception, stating clearly that an element is missing from the DOM.&lt;br&gt;
Relying solely on the *NoSuchElementException&lt;/em&gt; exception method can lead to incorrect failure, especially with dynamic elements or those with delayed loading. This approach can occasionally be misleading as it may trigger exceptions for dynamically generated web elements temporarily inaccessible to the driver.&lt;/p&gt;

&lt;p&gt;Below is the output generated when the web element could not locate and interact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2522%2F0%2AhXX3-hdCMKsANtyQ.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2522%2F0%2AhXX3-hdCMKsANtyQ.jpg" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To understand this better, let’s take an example.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException

driver = webdriver.Chrome()

class TestSelection(Setup):
    def should_select_text(self):
        try:  
            drop_down_button = "select-demo"
            selected_value = "selected-value"
            url = "https://www.lambdatest.com/selenium-playground/select-dropdown-demo"
            driver.maximize_window()
            driver.get(url)
            target_element = driver.find_element(By.ID, drop_down_button)
            drop_down = Select(target_element)
            selected = driver.find_element(By.CLASS_NAME, selected_value)
            drop_down.select_by_visible_text("Sunday")

            assert "Sunday" in selected.text, "The expected day not selected"

            driver.quit()
        except NoSuchElementException as e:
            driver.quit()
            print(e)

should_select_text_from_dropdown = TestSelection()

should_select_text_from_dropdown.should_select_text()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test code above masks the missing element errors for any selector using the &lt;em&gt;NoSuchElementException&lt;/em&gt; exception. If any of the selected web elements are missing from the DOM, this method prompts Selenium to return an exception and quit the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJu_qt4YwRONYTRP7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJu_qt4YwRONYTRP7.png" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dealing with dynamic elements, implementing custom error handling, and managing potential false test failures during &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium automation testing&lt;/a&gt; can be challenging. Inconsistent test results caused by dynamic web content and tests executed locally may lead to development delays.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Need to generate random text based on a regular expression for testing and generating sample data? Use our online tool to create &lt;a href="https://www.lambdatest.com/free-online-tools/random-data-from-regexp?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;random data from RegEx.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using cloud platforms
&lt;/h2&gt;

&lt;p&gt;Making use of a cloud-based service like LambdaTest can be proven beneficial. LambdaTest is an AI-powered test orchestration and execution platform that lets you run manual and automated tests at scale with over 3000+ real devices, browsers, and OS combinations.&lt;/p&gt;

&lt;p&gt;Along with web automation, LambdaTest also provides a &lt;a href="https://www.lambdatest.com/mobile-testing-lab?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;mobile device lab&lt;/a&gt;, which allows you to run tests on mobile devices, making it a complete solution for mobile app testing.&lt;/p&gt;

&lt;p&gt;It provides a wide range of real browsers and operating systems for comprehensive test coverage, ensuring that dynamic elements and web content variations are handled effectively.&lt;/p&gt;

&lt;p&gt;With cloud-based testing, developers can overcome inconsistencies caused by element readiness, reduce false test failures, and streamline the testing process. LambdaTest empowers teams to detect and address issues early in the development cycle, ultimately enhancing the reliability and quality of web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check if an element exists in Python Selenium on LambdaTest?
&lt;/h2&gt;

&lt;p&gt;We’ll use the &lt;a href="https://ecommerce-playground.lambdatest.io/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest eCommerce playground&lt;/a&gt; to demonstrate how to check if an element exists and run the test via the &lt;a href="https://www.lambdatest.com/selenium-grid-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium Grid&lt;/a&gt; using Python and pytest to run the test suite. Let’s begin with the steps to set up to run our test over LambdaTest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create a &lt;a href="https://accounts.lambdatest.com/detail/profile?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest account&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Get your Username and Access Key by going to your Profile avatar from the LambdaTest dashboard and selecting Account Settings from the list of options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AwsFIEo-azFe-46PI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AwsFIEo-azFe-46PI.png" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;**Step 3: **Copy your Username and Access Key from the &lt;a href="https://accounts.lambdatest.com/security?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Password and Security tab&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ASwLJ75yOiWFwTHn-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ASwLJ75yOiWFwTHn-.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Generate Capabilities containing details like your desired browser and its various operating systems. Generate your &lt;a href="https://www.lambdatest.com/capabilities-generator/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest Capabilities Generator&lt;/a&gt; as per your requirement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AEo0MAFblvoU2upr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AEo0MAFblvoU2upr5.png" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Now that you have both the Username, Access key, and capabilities copied, all you need to do is paste it on your test script.&lt;/p&gt;

&lt;p&gt;Having details collected from the LambdaTest platform, all you need to do is paste it accordingly into your test script; let’s cover each step in the following steps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Need realistic test data? Use our free online &lt;a href="https://www.lambdatest.com/free-online-tools/test-data-generator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;Test Data Generator&lt;/a&gt; tool to create realistic data for your testing needs. Get started now and save time and effort.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Project setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We must set up a few things before implementing the code with the LambdaTest platform. Let’s examine the steps individually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Inspecting element:&lt;/strong&gt; First, inspect the target web page using Chrome’s Inspect tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2As8jm3d59ZNM6i4r7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2As8jm3d59ZNM6i4r7.jpg" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Project structure:&lt;/strong&gt; Let’s take a look at the project structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkElementExists
├─ .env
├─ .gitignore
├─ examples
│  ├─ dropdown_exception.py
│  ├─ dropdown_using_count.py
│  └─ dropdown_using_display_enabled.py
├─ requirements.txt
├─ setup
│  └─ setup.py
└─ testsuites
   └─ test_e_commerce.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. VS Code:&lt;/strong&gt; Below is the test suite structure inside VS Code. The *examples *folder contains the test examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2312%2F0%2Azw_DikA1Hj92bfUb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2312%2F0%2Azw_DikA1Hj92bfUb.jpg" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use case
&lt;/h2&gt;

&lt;p&gt;The test scenario is simple. It first hovers over a product and then clicks the heart icon once visible and active to add the selected item to the wishlist. We chose this test scenario because the wishlist icon appears dynamically on mouse hover.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of the test steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Scenario&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Step 1: Open the target URL.&lt;br&gt;
Step 2: Scroll the target item into view and set the mouse on it.&lt;br&gt;
Step 3: Check for the web element’s existence using expected_conditions.&lt;br&gt;
Step 4: Check if the target web element is active and enabled.&lt;br&gt;
Step 5: Click the wishlist icon dynamically.&lt;/p&gt;

&lt;p&gt;The test setup is inside the setup/setup.py file, while the testsuites directory contains the test execution file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from dotenv import load_dotenv
import os
load_dotenv('.env')
LT_USERNAME = os.getenv("LT_USERNAME")
LT_ACCESS_KEY = os.getenv("LT_ACCESS_KEY")

options = webdriver.ChromeOptions()
options.browser_version = "latest"
options.platform_name = "Windows 10"
lt_options = {}
lt_options["username"] = os.getenv("LT_USERNAME")
lt_options["accessKey"] = os.getenv("LT_ACCESS_KEY")
lt_options["build"] = "e-commerce and dropdown use cases"
lt_options["project"] = "Elements Check Tests"
lt_options["name"] = "E-commerce and dropdown tests"
lt_options["console"] = "error"
lt_options["w3c"] = True
lt_options["plugin"] = "python-python"
options.set_capability('LT:Options', lt_options)

gridURL = "@hub.lambdatest.com/wd/hub"&amp;gt;https://{}:{}@hub.lambdatest.com/wd/hub".format(LT_USERNAME, LT_ACCESS_KEY)
class Setting:    
    def __init__(self):
        self.driver = webdriver.Remote(command_executor=gridURL, options= options)
    def setUp(self):
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()  
    def tearDown(self):
        if (self.driver != None):
            self.driver.quit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Step 1: We import the webdriver package from Selenium. It allows you to configure the browser and add the desired capabilities. We also import Python’s dotenv and the os package to mask and read environment variables from the .env file.&lt;/p&gt;

&lt;p&gt;Step 2: Next is an instantiation of the dotenv package and declaration of the LamdaTest grid username and access key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AbyMJQXKuEtZAJSYA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AbyMJQXKuEtZAJSYA.png" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; We instantiate a &lt;em&gt;ChromeOptions&lt;/em&gt; object as an &lt;em&gt;option&lt;/em&gt;. Then, we declared the browser version and platform name using the options object. The WebDriver will use these selections to set up the Chrome browser during the test execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuJRTFlhm1QB-AS2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuJRTFlhm1QB-AS2a.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; The &lt;em&gt;lt_options&lt;/em&gt; is an empty dictionary extended with the test capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2344%2F0%2AAvu-Wi4frToklgwM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2344%2F0%2AAvu-Wi4frToklgwM.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 5: Next, we set these capabilities and add them to ChromeOptions using the set_capability method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2A633CGU3TOM4Ztn0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2A633CGU3TOM4Ztn0t.png" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; We set the cloud grid URL to include our grid username and access key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AMQl5UEdZJZF1dp9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AMQl5UEdZJZF1dp9g.png" width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Generate cryptographically secure and unique random bytes with our&lt;a href="https://www.lambdatest.com/free-online-tools/random-byte-generator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt; Random Byte Generator&lt;/a&gt; secure for your project. Give it a try today!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Step 7: The Setting class’s &lt;strong&gt;init&lt;/strong&gt; function defines the driver attribute. It accepts the pre-defined options and sets the grid URL as the test executor using the webdriver’s remote method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3116%2F0%2A-oqq_5FjJKxK8-Nl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3116%2F0%2A-oqq_5FjJKxK8-Nl.png" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8:&lt;/strong&gt; Finally, we define the &lt;em&gt;setUp&lt;/em&gt; and &lt;em&gt;tearDown&lt;/em&gt; methods to maximize the browser window and quit the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9wS72fg-hwiTt16D.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9wS72fg-hwiTt16D.png" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s go through the test executor file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Filename — testsuite/test_e_commerce.py&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")
from setup.setup import Setting
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC

set_up = Setting()

class Selectors:
    item = "//img[@title='Apple Cinema 30{}']".format('"')
    wish_list = "wishlist-42"
    url = "https://ecommerce-playground.lambdatest.io/"
    action = ActionChains(set_up.driver)

class TestBuy(Selectors):    
    def test_add_item_to_wish_list(self):
        set_up.setUp()
        set_up.driver.get(self.url)
        item = set_up.driver.find_element(By.XPATH, self.item)
        set_up.driver.execute_script("arguments[0].scrollIntoView();", item)
        self.action.move_to_element(item).perform()

        element_present = False
        try:
            element_present = EC.presence_of_element_located((By.CLASS_NAME, self.wish_list))(set_up.driver)
        except:
            pass
        assert element_present, "element not found"

        wish_list = set_up.driver.find_element(By.CLASS_NAME, self.wish_list)
        assert wish_list.is_displayed(), "wishlist element not visible"
        assert wish_list.is_enabled(), "wishlist element is inactive"

      set_up.driver.execute_script("arguments[0].click();", wish_list)

        set_up.driver.implicitly_wait(10)

        set_up.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Code Walkthrough&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Step 1: We start the above code by appending the file path and importing the required modules. We import the Setting class from the setup folder to use the driver attribute, which contains the browser options and capabilities for the test suite. We also import &lt;a href="https://www.lambdatest.com/blog/what-is-actions-class-in-selenium/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;ActionChains&lt;/a&gt; and expected_conditions.&lt;/p&gt;

&lt;p&gt;Step 2: Using the ActionChain object, we can dynamically interact with a web element and perform k&lt;a href="https://www.lambdatest.com/blog/handling-keyboard-actions-in-selenium-webdriver/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;eyboard actions&lt;/a&gt; and mouse events like scrolling and hovering. As shown earlier, expected_conditions lets you check if the target web element exists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2560%2F0%2AjvbM4rlbe__bMxF3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2560%2F0%2AjvbM4rlbe__bMxF3.png" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Next, we instantiate the Setting class as set_up. Then, we declare the DOM selectors inside the Selectors class.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This class also attributes the target URL and instantiates the &lt;em&gt;ActionChains&lt;/em&gt; using the driver attribute from &lt;em&gt;Setting&lt;/em&gt;. It also contains the locators for the target web elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;item&lt;/em&gt; attribute is the product’s locator, while the &lt;em&gt;wish_list attribute&lt;/em&gt; is the heart icon locator.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2376%2F0%2A3MgdYoOo7XTidr8W.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2376%2F0%2A3MgdYoOo7XTidr8W.png" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 4: The TestBuy class is the test runner class. This class inherits the Selectors class to use its attributes. This class contains only one test method (test_add_item_to_wish_list), which starts by calling the setUp method of the Setting class to maximize the browser window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATwa9ak4__zqNSk3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATwa9ak4__zqNSk3r.png" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next is executing our test steps:&lt;/p&gt;

&lt;p&gt;Step 5: The test opens the target URL using the Selenium web driver’s get method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUUJzSzI9kszFtAsV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUUJzSzI9kszFtAsV.png" width="712" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before moving to the next step, we obtained the product element using Selenium’s &lt;em&gt;XPath&lt;/em&gt; attribute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2252%2F0%2AShq_5fDvsHAi7PnJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2252%2F0%2AShq_5fDvsHAi7PnJ.png" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 6: Use the &lt;a href="https://www.lambdatest.com/blog/scroll-a-webpage-in-selenium-using-java/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;scrollIntoView method in JavaScript&lt;/a&gt; to scroll the target item into view using Selenium’s execute_script. Then, set the mouse upon it using the ActionChain object. This initiates a hover action that makes the wishlist icon visible to a user. The perform method ensures that the ActionChains run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2684%2F0%2A_W2PwrT1R16a2amn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2684%2F0%2A_W2PwrT1R16a2amn.png" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; Check for the web element’s existence using &lt;em&gt;expected_conditions&lt;/em&gt;. We implement this using the &lt;em&gt;try/except block&lt;/em&gt;. We use a wildcard except to &lt;em&gt;pass&lt;/em&gt; possible errors since we don’t want Selenium to throw the built-in exception.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AHUFoRGc5C-yUx4UK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AHUFoRGc5C-yUx4UK.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The set_up.driver call ensures the WebDriver gets the browser session for the wish_list element.&lt;/p&gt;

&lt;p&gt;Once we assert that the wish_list element exists, we obtain it from the DOM using the inherited locator and querying it before the check might result in failing the test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2716%2F0%2AYtEuE8Az6ZQ-Ntld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2716%2F0%2AYtEuE8Az6ZQ-Ntld.png" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8:&lt;/strong&gt; Check if the target web element is active and enabled using the &lt;em&gt;is_displayed&lt;/em&gt; and &lt;em&gt;is_enabled&lt;/em&gt; methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2532%2F0%2AWgnF_xQurPWgZxJR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2532%2F0%2AWgnF_xQurPWgZxJR.png" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 9:&lt;/strong&gt; Click the wishlist icon dynamically using Selenium’s &lt;em&gt;execute_script&lt;/em&gt; method. This method allows you to execute JavaScript inside Python with Selenium. The &lt;em&gt;execute_script&lt;/em&gt; is ideal here, as the UI renders the wish_list element dynamically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AShAqpI-oWnkl7T7U.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AShAqpI-oWnkl7T7U.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To know more on how to use JavaScript executor, explore this blog on how to use JavaScript executor in Selenium WebDriver.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 10:&lt;/strong&gt; Finally, we call the set_up.tearDown to quit the browser and end the test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To run the test suite, open your command line to your test root folder and run the pytest command as shown.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test runs in the command line, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2482%2F0%2Azw_F8yreLO9LsCX1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2482%2F0%2Azw_F8yreLO9LsCX1.jpg" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the automation test execution on the Selenium cloud grid:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AfG7oalwV0K9z_Y2f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AfG7oalwV0K9z_Y2f.jpg" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Looking for a unique username? Generate usernames with our &lt;a href="https://www.lambdatest.com/free-online-tools/random-username-generator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov_02&amp;amp;utm_term=bh&amp;amp;utm_content=free_online_tools" rel="noopener noreferrer"&gt;Random Username Generator&lt;/a&gt;! Quick, easy, and fun.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In automation testing, it’s common to overlook the need for element existence checks. However, it’s important to remember that web elements are only sometimes readily visible. Incorporating this validation into your testing approach is crucial to keep your test suite aligned with the ever-changing software.&lt;/p&gt;

&lt;p&gt;In this blog, we’ve explored various practical methods for checking if an element exists in Python Selenium. Our initial examples and test demonstrations provide simple, effective solutions to strengthen your test strategies. By using these approaches, you’ll improve the reliability of your automation tests and ensure that your software remains consistent, even when dealing with dynamic web elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How to check if the element is visible in Python Selenium?
&lt;/h3&gt;

&lt;p&gt;Use is_displayed() method. It returns True if the element is visible on the web page and False if not.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you verify dynamic elements in Selenium?
&lt;/h3&gt;

&lt;p&gt;Use explicit waits in Selenium to ensure that the element we are looking for is available before we interact with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you find hidden elements in Python Selenium?
&lt;/h3&gt;

&lt;p&gt;Hidden elements exist in the webpage’s source code but are not visible to users when they view the page. You can locate these hidden elements in Selenium by using attributes such as class name or ID. It’s important to note that even if you interact with these hidden elements using Selenium, these interactions may not produce any visible changes on the webpage that a user can see.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Pytest Django Tutorial: Testing Your Django Apps With Selenium Pytest</title>
      <dc:creator>Idowu Omisola</dc:creator>
      <pubDate>Thu, 13 Apr 2023 07:49:34 +0000</pubDate>
      <link>https://dev.to/testmuai/pytest-django-tutorial-testing-your-django-apps-with-selenium-pytest-11po</link>
      <guid>https://dev.to/testmuai/pytest-django-tutorial-testing-your-django-apps-with-selenium-pytest-11po</guid>
      <description>&lt;p&gt;Django reduces the development complexities of large-scale websites. But when developing a website with Django, &lt;a href="https://www.lambdatest.com/automated-ui-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;UI automation testing&lt;/a&gt; is as essential as unit testing. Even if your team operates a CI/CD pipeline, you want to ensure you catch bugs earlier and deliver a tested build to the production environment. Although Django’s built-in test client provides a dummy browser for &lt;a href="https://www.lambdatest.com/learning-hub/functional-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;functional testing&lt;/a&gt;, it has many limitations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium &lt;/a&gt;overcomes these limitations and comes to mind when testing the template structure, user-DOM interaction, and JavaScript responsiveness. However, for fast, scalable, and measurable Django automation UI testing, a combination of pytest and Selenium gives an excellent result.&lt;/p&gt;

&lt;p&gt;As for pytest, it has many valuable built-in features and plugins, making it an ideal testing tool for heavy-duty web frameworks. Thankfully, Django supports pytest and Selenium.&lt;/p&gt;

&lt;p&gt;This pytest Django tutorial will teach you how to test your locally hosted Django website on a cloud grid using Selenium and Python. You’ll also see how you can repeat this test in a live version of your Django website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test your native, hybrid, and web apps across all legacy and latest mobile operating systems on the most powerful &lt;a href="https://www.lambdatest.com/android-emulator-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Android emulator&lt;/a&gt; online.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of using pytest for Django automated testing
&lt;/h2&gt;

&lt;p&gt;Pytest has some features that make it an ideal Django testing tool. While you might also use the unittest module for &lt;a href="https://www.lambdatest.com/python-automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Python automation testing&lt;/a&gt;, pytest makes your test easy to read and supports &lt;a href="https://www.lambdatest.com/blog/parameterization-in-pytest-with-selenium/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;parameterized testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below are more benefits of using this framework for pytest Django automation testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameterization&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pytest allows you to parameterize your test, simplifying the test class or function and eliminating code chunks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fixtures&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pytest’s fixtures are some of its most valuable features. They help you to manage the test data and separate test code from dependencies. For example, pytest fixtures can be handy for interacting with the database and creating users in a Django app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Support for third-party and built-in plugins&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its support for many third-party and built-in plugins makes it a versatile tool for automation and &lt;a href="https://www.lambdatest.com/learning-hub/python-unit-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Python unit testing&lt;/a&gt;. Some examples of plugins that work seamlessly with pytest include coverage.py and pytest-BDD for code coverage and behavior-driven tests, respectively&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Support for other testing libraries&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pytest works seamlessly with other testing libraries, including unittest for unit testing and Selenium for UI automated testing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy Assertions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike unittest, which uses several assertion types, pytest validates expected results using only the assert keyword.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Django testing support&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the help of the pytest-django library, pytest provides full support for Django UI automation testing and &lt;a href="https://www.lambdatest.com/learning-hub/unit-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;unit testing&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Detail-oriented&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pytest provides detailed test information, including the test timeframe and the number of test runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are pytest fixtures?
&lt;/h2&gt;

&lt;p&gt;We’ll store the admin registration information for our test using pytest fixtures in this pytest Django tutorial.&lt;/p&gt;

&lt;p&gt;So what are pytest fixtures?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/blog/end-to-end-tutorial-for-pytest-fixtures-with-examples/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Pytest fixtures&lt;/a&gt; are custom functions that allow you to separate test data and dependencies from the test suite. Fixtures are reusable, making the test code less complex. While they might present limitations in some use cases, they’re customizable and can work in different capacities.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1GTBAtCSSco"&gt;
&lt;/iframe&gt;
&lt;br&gt;
You can also Subscribe to the &lt;a href="https://www.youtube.com/channel/UCCymWVaTozpEng_ep0mdUyw?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=youtube" rel="noopener noreferrer"&gt;LambdaTest YouTube Channel &lt;/a&gt;and stay updated with the latest tutorials around &lt;a href="https://www.lambdatest.com/automated-browser-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated browser testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Cypress E2E testing&lt;/a&gt;, CI/CD, and more.&lt;/p&gt;

&lt;p&gt;You can convert a function into a pytest fixture by adding a fixture decorator (@ pytest .fixture), which accepts an optional scope keyword argument. Pytest fixtures even pair seamlessly with Selenium for &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated testing.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, consider testing a website if it has a particular string in its title. You can separate the test string from the function that gets the website’s title using the pytest fixture, as shown below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver

import pytest

@pytest.fixture
def webPageTitle():
    driver = webdriver.Chrome()
    driver.get("https://www.lambdatest.com/automation-demos")
    return driver.title

@pytest.fixture
def titleString():
    return "Selenium"


def test_string_in_webPage_title(webPageTitle, titleString):
   assert titleString in webPageTitle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Running the above test using the pytest command runs as shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2672%2F0%2AtqtLzU1SknpE9ky5.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2672%2F0%2AtqtLzU1SknpE9ky5.jpeg" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Mobile &lt;a href="https://www.lambdatest.com/mobile-emulator-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;emulators online&lt;/a&gt; from LambdaTest allows you to seamlessly test your mobile applications, websites,and web apps on mobile browsers and mobile devices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Holding Test Fixtures: What is the conftest.py file?
&lt;/h2&gt;

&lt;p&gt;The conftest.py file connects your fixtures automatically with your test suite without explicitly importing them. So while fixtures are optional and may not be applicable in all test types, pytest looks for them inside conftest.py.&lt;/p&gt;

&lt;p&gt;By default, pytest only recognizes fixtures written within the same module. But the conftest.py file allows you to use them across your test directory.&lt;/p&gt;

&lt;p&gt;When you write fixtures in the conftest.py file, you don’t need to import them explicitly in your test. Pytest automatically recognizes all functions (with the fixture decorator) inside conftest.py as fixtures.&lt;/p&gt;

&lt;p&gt;While pytest maps fixtures in conftest.py automatically, you can’t call them directly in your test modules. You use another pytest fixture to handle the main one indirectly to use it in your test class or function.&lt;/p&gt;

&lt;p&gt;For instance, we can rearrange the previous example above by isolating the fixtures from the test function. This also allows us to isolate test dependencies.&lt;/p&gt;

&lt;p&gt;To achieve this, create a new test folder. Make a new conftest.py and a test.py file inside that folder. Then separate the test concerns as shown.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver

import pytest

@pytest.fixture
def webPage():
    driver = webdriver.Chrome()
    driver.get("https://www.lambdatest.com/automation-demos")
    return driver.title

@pytest.fixture
def titleString():
    return "Selenium"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;def test_string_in_webPage_title(webPage, titleString): assert titleString in webPage&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_string_in_webPage_title(webPage, titleString):
   assert titleString in webPage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As seen in the example above, you don’t need to import the fixture explicitly into test.py to use them.&lt;/p&gt;

&lt;p&gt;Open your terminal to your test folder and run the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest test.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test runs successfully, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2702%2F0%2AR-IZLi1zdhi21cOO.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2702%2F0%2AR-IZLi1zdhi21cOO.jpeg" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parameterized Fixtures
&lt;/h2&gt;

&lt;p&gt;Fixtures are also parameterizable, allowing you to execute several tests in one test function. Let’s take a quick look at its usage in the following example.&lt;/p&gt;

&lt;p&gt;In this section of the pytest Django tutorial, you will visit two websites and check if the action is successful by asserting that a particular string is present in each web title.&lt;/p&gt;

&lt;p&gt;You could write the test for each website as a boilerplate, as shown:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver

driver = webdriver.Chrome()

first_website = "https://www.lambdatest.com/automation-demos"
second_website = "https://www.lambdatest.com"

def test_first_web_page():
    driver.get("https://www.lambdatest.com/automation-demos")
    assert "Selenium" in driver.title, "Selenium should be in the title"

def test_second_web_page():
    driver.get("https://www.lambdatest.com")
    assert "LambdaTest" in driver.title, "LambdaTest should be in the title"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The two tests pass, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2972%2F0%2Ax1CIW8ALR3-ikkBE.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2972%2F0%2Ax1CIW8ALR3-ikkBE.jpeg" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But we can eliminate this boilerplate by passing the websites as parameters in our test function. Hence, a single test function validates the result instead of the separate units.&lt;/p&gt;

&lt;p&gt;When parameterized, the code becomes the following.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pytest

from selenium import webdriver

driver = webdriver.Chrome()

first_website = "https://www.lambdatest.com/automation-demos"
second_website = "https://www.lambdatest.com"

@pytest.mark.parametrize("allWebsites", [first_website, second_website])
def test_all_customer_outputs(allWebsites):
   driver.get(allWebsites)
   assert "Selenium" and "LambdaTest" in driver.title, "Selenium and LambdaTest must be in titles"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test visits each website in the list and validates the input data, as shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2932%2F0%2A6OzfxxRv_pBIBZoy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2932%2F0%2A6OzfxxRv_pBIBZoy.jpeg" width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, while a parameterized fixture shortens the code, its limitation is that you might not have the flexibility of customizing the error message for each expected output, as done in the previous chunked code above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up pytest Django Project
&lt;/h2&gt;

&lt;p&gt;If you don’t already have a running pytest Django project, you can set it up using the brief explanation below if you’ve not done so already. This pytest Django tutorial runs on Python 3.10.6. But earlier versions also work perfectly. So we also assume you have Python running on your machine.&lt;/p&gt;

&lt;p&gt;To start, create a project directory and make a new Python virtual environment in that folder. For this stage, you can use the &lt;em&gt;virtualenvwrapper&lt;/em&gt; or Python’s built-in &lt;em&gt;virtualenv&lt;/em&gt; package, depending on what works best for you. Ignore this step if you’re already working in a virtual machine or your project uses a containerized environment.&lt;/p&gt;

&lt;p&gt;Next, install Django in your virtual environment.&lt;/p&gt;

&lt;p&gt;We also used the markdown package for the website demo used in this pytest Django tutorial. So while it’s not a requirement, you might want to install it.&lt;/p&gt;

&lt;p&gt;Create a requirements.txt file in your project root folder and list the packages as shown.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;django  
django-markdown-deux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;While &lt;strong&gt;django-markdown-deux&lt;/strong&gt; is optional, it provides a markdown template for the pytest Django project. So I’ve added it since it’s a requirement for the Django project used in this pytest Django tutorial to work as expected.&lt;/p&gt;

&lt;p&gt;Run the installation of the requirements using pip:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The installation runs as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2688%2F0%2AqC0gYBDpKTJqNOtj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2688%2F0%2AqC0gYBDpKTJqNOtj.jpeg" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_Let’s take a look which are the most wanted &lt;a href="https://www.lambdatest.com/blog/automation-testing-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automated testing tools&lt;/a&gt; that have climbed the top of the ladder so far? _&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Django for large-scale websites?
&lt;/h2&gt;

&lt;p&gt;The 2022 Stack Overflow Developer Survey shows that Python is one of the easiest programming languages. Since Django is a Python web framework, it allows you to develop a complex website by leveraging Python’s simplicity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2290%2F0%2AkZNafs_LSMQM5WIs.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2290%2F0%2AkZNafs_LSMQM5WIs.jpeg" width="800" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some alternatives to Django include Flask, Pyramid, web2.py, CherryPy, Tornado, and FastAPI, among others. But Django’s structure smoothens the development pipeline, helping the development team to achieve a viable product on time.&lt;/p&gt;

&lt;p&gt;Besides testing support, here are some reasons Django is suitable for developing large-scale websites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Django offers a robust and horizontally scalable architecture that allows you to add more layers to your website. Its URL pattern gives it rigidity for accommodating multiple requests at a time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Top-notch security features&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Django offers built-in security against cross-site scripting (XSS), clickjacking using the X-Frame-Option middleware, cross-site request forgery (CSRF), and SQL injection using query sets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Built-in admin interface&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building an admin interface consumes development time. Django eliminates this, as it comes with a built-in, well-styled admin engine that’s easy to use for content creators and less programming-savvy individuals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Object-relational mapping (ORM) support&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Django’s ORM support allows it to link several models seamlessly in relational databases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Seamless database setup&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Django’s settings.py file&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy SMTP integration&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can configure an SMTP protocol easily inside the settings.py. It also supports third-party, real-time SMTP monitoring tools like Sentry.&lt;/p&gt;

&lt;p&gt;These features reduce development time, making Django a suitable Python framework for developing complex websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing a Django application with pytest
&lt;/h2&gt;

&lt;p&gt;The next step is to configure your pytest Django project. This involves creating an initiation file that points your tests to your Django project settings file. But let’s install more dependencies before moving ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation of Test Dependencies
&lt;/h2&gt;

&lt;p&gt;Since this pytest Django tutorial demonstrates how to use Selenium and pytest for UI &lt;a href="https://www.lambdatest.com/blog/python-automation-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automation testing with Python &lt;/a&gt;in Django, we’ll install pytest, pytest-django, and Selenium.&lt;/p&gt;

&lt;p&gt;To install these test packages, append the list of dependencies in your requirements.txt file as shown.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;django
django-markdown-deux
pytest
pytest-django
selenium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, run the installation again.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The installation runs as shown. Note how it skips the dependencies we installed previously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AVVE9aRmaOYukwAk-.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AVVE9aRmaOYukwAk-.jpeg" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_With LambdaTest achieve faster, reliable, and scalable testing in a secure and efficient manner. Join thousands of users who trust our &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automation testing platform&lt;/a&gt; for their testing needs. _&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is pytest-django?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.lambdatest.com/automation-testing-advisor/python/pytest-django_python?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;pytest-django&lt;/a&gt; module is a pytest plugin that facilitates Django testing with pytest. It also lets you configure your pytest Django project to work inside the pytest.ini file.&lt;/p&gt;

&lt;p&gt;Generally, pytest-django is the plugin that allows pytest to identify your Django project. Additionally, it lets you use pyest’s marker helpers, fixtures, and other pytest plugins with Django without hassle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration of pytest.ini
&lt;/h2&gt;

&lt;p&gt;Next, create a &lt;em&gt;pytest.ini&lt;/em&gt; file in your project root. This is an initialization file that connects your Django project with pytest. You can configure your test behavior using this file, including default database usage.&lt;/p&gt;

&lt;p&gt;Below is the simple configuration used in this pytest Django tutorial.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[pytest]

DJANGO_SETTINGS_MODULE = django_blog.settings
filterwarnings = ignore::DeprecationWarning
addopts = --reuse-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;DJANGO_SETTINGS_MODULE points our test to the pytest Django project settings file. This is a feature of the pytest-django plugin that allows pytest to inherit the configurations of your Django project.&lt;/p&gt;

&lt;p&gt;We use &lt;em&gt;filterwarnings&lt;/em&gt; to ignore deprecation warnings since we want to see a clean log of our test runs. We also like the &lt;a href="https://www.lambdatest.com/learning-hub/test-execution?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test execution&lt;/a&gt; to be as fast as possible. So we declare &lt;em&gt;–reuse-db&lt;/em&gt; in the addopts configuration to allow our test to re-use the previous database instead of creating a new one for each test instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creation of Django Test Directory
&lt;/h2&gt;

&lt;p&gt;A dedicated test folder will enable you to separate your test suite from your pytest Django project. Doing this can be handy when the test codebase is large.&lt;/p&gt;

&lt;p&gt;Go to your Django project root directory and create a new test folder. You can create other folders within this directory to handle your test files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2472%2F0%2Aa0l01mW6XiLeexnq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2472%2F0%2Aa0l01mW6XiLeexnq.jpeg" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is how the project structure looks in VS Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2296%2F0%2A1jH1O2DFvfUg1uUI.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2296%2F0%2A1jH1O2DFvfUg1uUI.jpeg" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a closer look at the tests folder to see what each directory and file does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FolderName&lt;/strong&gt; — &lt;em&gt;Blog-app/blog/tests&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2180%2F0%2AGDqHxGPd9frOTL8q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2180%2F0%2AGDqHxGPd9frOTL8q.jpeg" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Do you use a Mac and want to run the test in Internet Explorer? This article explores how to test &lt;a href="https://www.lambdatest.com/blog/test-internet-explorer-for-mac/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Internet Explorer on Mac&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Directory Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Django test directory structure typically includes a “tests” module within each Django app directory, where app-specific tests can be organized and stored. Additionally, the project directory may also contain a top-level “tests” directory for project-wide tests that don’t belong to a specific app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sel_selectors directory:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;sel_selectors&lt;/em&gt; folder contains the module that handles all &lt;a href="https://www.lambdatest.com/blog/document-object-model/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;DOM&lt;/a&gt; selectors for Selenium (sel_selectors.py). This module holds the selector class used to perform web actions in the test runner file (&lt;em&gt;test_runner/test_module.py&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;setup folder:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;setup&lt;/em&gt; directory has the file containing general test requirements and driver configuration for the Django test (&lt;em&gt;setup.py)&lt;/em&gt;. The &lt;em&gt;setup.py&lt;/em&gt; file provides the Settings class for accessing the grid, opening the browser instance, closing the browser, and quitting the test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;test_runner folder:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This folder contains the main Python file (&lt;em&gt;test_module.py&lt;/em&gt;) that runs the test suite and feeds pytest with relevant test information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo: Testing the Django application with pytest
&lt;/h2&gt;

&lt;p&gt;Let’s briefly explain our Django test goal before we begin.&lt;/p&gt;

&lt;p&gt;Our project is a simple blog with an admin backend where a superuser can publish posts. So our test goal is to create the superuser for each test instance, visit the login page and log into the admin panel. Then fill in the form fields.&lt;/p&gt;

&lt;p&gt;Below is a screenshot of the login page for our locally hosted Django website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2144%2F0%2AEg9ioQ9tQCJdjM18.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2144%2F0%2AEg9ioQ9tQCJdjM18.jpeg" width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then finally, we publish a post by ticking the Published checkbox and clicking the Submit button.&lt;/p&gt;

&lt;p&gt;The admin page of the locally hosted Django website looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AFRqSD87XXzxJb5oU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AFRqSD87XXzxJb5oU.png" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We expect to visit the homepage after publishing a post. So we create an action for that action as well. See the homepage below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3144%2F0%2ApeoXMQPoydjXuT-r.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3144%2F0%2ApeoXMQPoydjXuT-r.jpeg" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This section of the pytest Django tutorial will demonstrate the test using the locally hosted pytest Django project. We will do the same when finally hosted — you’ll see this later in the section of this pytest Django tutorial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Scenario:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below are our test steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log on to the login page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill out the username and password fields with the superuser’s credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the login button to enter the post editor engine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill out the post fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tick the Published checkbox.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Submit to publish the post and visit the homepage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Set up your Grid Tunnel to allow local testing
&lt;/h2&gt;

&lt;p&gt;To run the locally hosted Django website, you need a tunnel to establish a connection with a &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium cloud grid&lt;/a&gt;, like LambdaTest. So the tunnel serves as a temporary server for each test instance.&lt;/p&gt;

&lt;p&gt;LambdaTest is a digital experience testing platform that enables you to perform &lt;a href="https://www.lambdatest.com/python-web-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Python web automation&lt;/a&gt; across 3000+ real browsers and platform combinations. It supports different Python-based testing frameworks like pytest for &lt;a href="https://www.lambdatest.com/selenium-python-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium Python testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Visit our support documentation to &lt;a href="https://www.lambdatest.com/support/docs/python-with-selenium-running-python-automation-scripts-on-lambdatest-selenium-grid/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=support_doc" rel="noopener noreferrer"&gt;get started with Selenium Python testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To set up a tunnel on the LambdaTest cloud grid:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download a compatible version of the tunnel from LambdaTest. Extract the file once downloaded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to the build section of your dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Configure Tunnel&lt;/strong&gt; at the right.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the tunnel connection string.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ao1-brIMkCPAGAeW2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ao1-brIMkCPAGAeW2.jpg" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open your command line to the extracted tunnel file destination.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste the copied string in the command line and press enter to start your tunnel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The tunnel runs as shown below.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AwGYZKodaVFeMbjB0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AwGYZKodaVFeMbjB0.jpg" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When you refresh your builds dashboard, &lt;strong&gt;Tunnel active&lt;/strong&gt; replaces &lt;strong&gt;Configure Tunnel&lt;/strong&gt; at the top right.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ae84998ezyd3uiRik.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ae84998ezyd3uiRik.jpg" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Are you using Playwright for automation testing? Run your &lt;a href="https://www.lambdatest.com/playwright-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Playwright test&lt;/a&gt; scripts instantly on 50+ browser/OS combinations using the LambdaTest cloud.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a conftest.py file
&lt;/h2&gt;

&lt;p&gt;As mentioned, the &lt;em&gt;conftest.py&lt;/em&gt; file holds test fixtures, which are perfect for handling test data, states, and dependencies.&lt;/p&gt;

&lt;p&gt;In this pytest Django tutorial, we handle the superuser creation function for our test using the pytest fixture. We place it inside conftest.py since we want to separate it from the bulk Django test suite.&lt;/p&gt;

&lt;p&gt;To add the conftest.py file to your Django test suite, create a new file in your test folder and name it &lt;em&gt;conftest.py.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Below is our superuser creation fixture.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.contrib.auth.models import User
import pytest
import os
from dotenv import load_dotenv
load_dotenv('.env')
from django.test import LiveServerTestCase

@pytest.fixture
def superAdmin() -&amp;gt; User:
    return User.objects.create_user(
         'admin',
         'omisolaidowu@gmail.com,',
       os.getenv('SUPER_ADMIN_PASSWORD'),
       is_superuser=True
       )

@pytest.mark.usefixtures("superAdmin")
class admin(LiveServerTestCase):
  @pytest.fixture(autouse=True)
  def super(self, superAdmin):
    self.createSuperAdmin = superAdmin
    return self.createSuperAdmin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code creates a superuser for logging into the Django app. This fixture runs only once. So we don’t need to bother about duplicate user keys.&lt;/p&gt;

&lt;p&gt;Creating a superuser for our test is easy since Django has a built-in User model. We import the User model from Django to create a superuser in the superAdmin function, which returns a User instance. Using the &lt;em&gt;@pytest.fixture&lt;/em&gt; decorator, pytest sees this function as a fixture.&lt;/p&gt;

&lt;p&gt;We also import the &lt;em&gt;LiverServerTestCase&lt;/em&gt; class from Django. This provides a live server for running the UI test. When inherited, we can mimic a live test using the &lt;em&gt;liver_server_url&lt;/em&gt; attribute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjqWKzy0DhzO62tTR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjqWKzy0DhzO62tTR.png" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, &lt;em&gt;superAdmin&lt;/em&gt; is a base fixture. Django knows to create a superuser from the given parameters because &lt;em&gt;we set is_superuser&lt;/em&gt; to True.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AENo5tHlRTgx0ubF4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AENo5tHlRTgx0ubF4.png" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we mentioned, you can’t call a fixture directly in a test without passing it to a handler (typically, another fixture).&lt;/p&gt;

&lt;p&gt;While you can call a fixture inside another directly without issues, it’s different when dealing with a class, as we need to pass the &lt;em&gt;@ pytest. mark. usefixtures&lt;/em&gt; decorator over it.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;@ pytest. mark. usefixtures&lt;/em&gt; decorator allows you to specify the fixture to use in a class method. In this case, the admin class can feed its methods with the superAdmin function fixture, as listed in the usefixture decorator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0wYf7CUXAnCzL5zZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0wYf7CUXAnCzL5zZ.png" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although the test runner class (&lt;em&gt;test_module.py&lt;/em&gt;) might inherit &lt;em&gt;LiverServerTestCase&lt;/em&gt; directly, the admin class inherits it instead since the test runner class will still inherit the admin class.&lt;/p&gt;

&lt;p&gt;Thus, while the test runner class inherits the admin attributes, it also does so &lt;em&gt;LiverServerTestCase&lt;/em&gt; and can use the &lt;em&gt;liver_server_url&lt;/em&gt; attribute from that class to open the web URL.&lt;/p&gt;

&lt;p&gt;The super method has to be a fixture since only a pytest fixture can call another one directly before it’s usable in a test class or function. This class method returns an admin attribute (&lt;em&gt;self.createSuperAdmin&lt;/em&gt;) using the &lt;em&gt;superAdmin Pytest&lt;/em&gt; fixture.&lt;/p&gt;

&lt;p&gt;Hence, calling &lt;em&gt;self.createSuperAdmin&lt;/em&gt; in our test runner class creates a superuser with the specified email address and username for every test execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aw7dcnu2GdgsLJwbL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aw7dcnu2GdgsLJwbL.png" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the Django test
&lt;/h2&gt;

&lt;p&gt;The test setup follows the typical setup and tear-down functions for expanding the browser window and closing it, respectively.&lt;/p&gt;

&lt;p&gt;However, you need to grab your grid username and access key if you’re using a cloud grid, as you need to provide these inside your desired capabilities.&lt;/p&gt;

&lt;p&gt;If you’re using the LambdaTest cloud grid, follow these steps to get your username and access key.&lt;/p&gt;

&lt;p&gt;1.Log into your &lt;a href="https://accounts.lambdatest.com/dashboard/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest Dashboard&lt;/a&gt; and go to the **Builds **directory.&lt;/p&gt;

&lt;p&gt;2.Click the Access Key at the top right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AqRWkqiTl3BKKSOcX.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AqRWkqiTl3BKKSOcX.jpg" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.Copy the Username and Access Key fields and paste them into your environment variable (&lt;em&gt;.env&lt;/em&gt;) file as shown.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LT_USERNAME = "Paste your username"&lt;br&gt;
    LT_ACCESS_KEY = "Paste your access key"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let’s go ahead with the Django UI automation test setup.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from dotenv import load_dotenv
import os
load_dotenv('.env')

LT_USERNAME = os.getenv("LT_USERNAME")
LT_ACCESS_KEY = os.getenv("LT_ACCESS_KEY")


desired_caps = {
        'LT:Options' : {
            "user" : LT_USERNAME,
            "accessKey" : LT_ACCESS_KEY,
            "build" : "Django Functional Testing",
            "name" : "Django Test",
            "platformName" : "Windows 10",
            "tunnel": True

        },
        "browserName" : "FireFox",
        "browserVersion" : "103.0",

    }

class Settings:

    def __init__(self) -&amp;gt; None:
        self.grid_url = "@hub.lambdatest.com/wd/hub"&amp;gt;https://{}:{}@hub.lambdatest.com/wd/hub".format(
            LT_USERNAME, LT_ACCESS_KEY
            )
        self.desired_caps = desired_caps
        self.driver = webdriver.Remote(command_executor=self.grid_url, desired_capabilities= self.desired_caps)

    def setup(self):
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
    def tearDown(self):
        if (self.driver != None):
            print("Cleaning the test environment")
            self.driver.quit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We start the setup by importing the &lt;a href="https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium WebDriver.&lt;/a&gt; Next is the extraction of our grid username and access key from the .env file using the &lt;em&gt;os.getenv&lt;/em&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2ATlSsqi49bChYsLcM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2ATlSsqi49bChYsLcM.png" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specifying these variables inside the desired capabilities, as shown below, allows us to access the cloud grid browser and platform instance. And since the test uses a tunnel, we also add a tunnel option to &lt;em&gt;desired_caps&lt;/em&gt; and set it to True, so the Selenium cloud grid knows we’re testing from a local machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2160%2F0%2A8L58xsxZVTZzND3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2160%2F0%2A8L58xsxZVTZzND3v.png" width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;Since setting tunnel to True is only applicable when testing a locally hosted website, remove or set it to False when switching to a live test.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The grid URL also requires the username and access key for full access to the cloud grid. We declare this as an attribute of the Settings class. We further use this to configure the Selenium web driver (&lt;em&gt;passed as self.driver&lt;/em&gt;), as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AOGvKJFIA3uvsjBPh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AOGvKJFIA3uvsjBPh.png" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up are the setup and tearDown functions. The setup delays the browser for 10 seconds for the DOM to load resources. It then maximizes the browser window for web access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEaSa5OryOEn1wsQw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEaSa5OryOEn1wsQw.png" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tearDown function checks if the test has a running driver and quits it if the condition is True.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2132%2F0%2AJaYcnEFdr53qSJcN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2132%2F0%2AJaYcnEFdr53qSJcN.png" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the tearDown function must execute after the test runs all required scenarios. Otherwise, calling tearDown before any test scenario will close the browser and quit the Django test before completion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;LambdaTest’s mobile &lt;a href="https://www.lambdatest.com/mobile-emulator-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;emulator online&lt;/a&gt; platform allows you to seamlessly test your mobile applications, websites, and web apps on various mobile browsers and devices, without having to own or physically access them.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Selenium Selector Class
&lt;/h2&gt;

&lt;p&gt;Getting the selectors from the DOM is easy since the project is probably still on your local machine. Even if you’ve deployed to production, inspecting the DOM via the browser exposes the web elements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inspecting the web elements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project is still locally hosted in this case. We need Selenium to interact with two templates; &lt;em&gt;templates/engine.html *and *templates&lt;/em&gt;/login.html.&lt;/p&gt;

&lt;p&gt;Let’s view the login template to assess its DOM structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A26_OoPsIPI7Rhe9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A26_OoPsIPI7Rhe9w.png" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The engine template inherits its elements from the Django forms attribute. This is because we only want to call the form in the HTML template. Let’s see the &lt;em&gt;forms.py&lt;/em&gt; file used in this pytest Django project for clarity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AcoubwuDQm80gsUwU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AcoubwuDQm80gsUwU.png" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The submit element is missing from the above form. You can find that in the original engine template.&lt;/p&gt;

&lt;p&gt;Below is the original engine template. Look closely, and you’ll see that the Submit button has an id and a class of &lt;strong&gt;submit **and **submit-button&lt;/strong&gt;, respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AxbVvS5xSYF17uRWb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AxbVvS5xSYF17uRWb.png" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, you can inspect the website to pick the &lt;a href="https://www.lambdatest.com/learning-hub/selenium-locators?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium locators&lt;/a&gt; for each DOM element involved in the test.&lt;/p&gt;

&lt;p&gt;For instance, to get the class selectors for the login form, visit the login URL and open the DOM structure using the browser’s inspect tool. Here’s what you get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AimVldE6LESII64cy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AimVldE6LESII64cy.jpg" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now let’s create the selector module for our Django UI test&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver.common.by import By
from dataclasses import dataclass

class formLocator:
    username = "username-fill" #class
    password = "password-fill" #class
    loginSubmit = "Login" #name
    published = "id_published" #id
    title = "my-title" #class
    content = "content-field" #class
    description = "-content-description" #class
    blogSubmit = "submit" #IDs


locate = formLocator()

@dataclass
class Webactions():
    driver: object

    def getWeb(self, URL):
        self.driver.get(URL)

    def getTitle(self):
        return self.driver.title

    def current_url(self):
        return self.driver.current_url

    def fill_username(self, username):
        self.driver.find_element(By.CLASS_NAME, locate.username).send_keys(username)

    def fill_password(self, password):
        self.driver.find_element(By.CLASS_NAME, locate.password).send_keys(password)

    def submit_login(self):
        self.driver.find_element(By.NAME, locate.loginSubmit).click()

    def published_yes(self):
        self.driver.find_element(By.ID, locate.published).click()

    def enter_title(self, title):
        self.driver.find_element(By.CLASS_NAME, locate.title).send_keys(title)

    def write_content(self, content):
        self.driver.find_element(By.CLASS_NAME, locate.content).send_keys(content)

    def enter_description(self, description):
        self.driver.find_element(By.CLASS_NAME, locate.description).send_keys(description)

    def submit_post(self):
        self.driver.find_element(By.ID, locate.blogSubmit).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;formLocator&lt;/em&gt; class contains the DOM selectors for the target web page. Thus, each is an attribute of the &lt;em&gt;formLocator&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;Looking closely, every other selector in the &lt;em&gt;formLocator&lt;/em&gt; class besides the submit buttons, username, and password fields inherit its identifier from the Django form shown previously.&lt;/p&gt;

&lt;p&gt;Below is an extract of the &lt;em&gt;formLocator&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2036%2F0%2APOYUfRfDp_zzNs1T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2036%2F0%2APOYUfRfDp_zzNs1T.png" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also create a Webactions class to act on these selectors. The dataclass decorator adds a driver initiator to the &lt;em&gt;webActions object&lt;/em&gt;. We’ve previously imported &lt;em&gt;dataclass&lt;/em&gt; from Python’s built-in &lt;em&gt;dataclasses&lt;/em&gt; package.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFV9vsI6hpZACbbhY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFV9vsI6hpZACbbhY.png" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus, &lt;em&gt;webAction&lt;/em&gt; instantiates with the Selenium WebDriver, which comes from the setup module (you’ll see the usage in the test runner (&lt;em&gt;test_module.py&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A-2Xaqxj0IiNMFkcD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A-2Xaqxj0IiNMFkcD.png" width="588" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is similar to using the &lt;em&gt;&lt;strong&gt;init&lt;/strong&gt;&lt;/em&gt; method like so:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def __init__(self, driver):
    self.driver = driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;getWeb&lt;/em&gt;, &lt;em&gt;getTitle&lt;/em&gt;, and &lt;em&gt;current_url&lt;/em&gt; methods of Webactions class fetch the website’s URL, the current page title, and the current page URL, respectively. While you can achieve this directly using &lt;em&gt;driver.get&lt;/em&gt;, this approach allows you to customize and abstract your test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQjh1VphXqEQGVPAe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQjh1VphXqEQGVPAe.png" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other methods in the Webactions class interact with the DOM selectors using the Selenium **By **class (we’ve imported this previously). However, those requiring form filling take an argument each.&lt;/p&gt;

&lt;p&gt;For instance, a method whose selector uses an ID identifier locates its element using &lt;strong&gt;By&lt;/strong&gt; ID. Each class method accesses the selectors by calling them from the &lt;em&gt;formLocator&lt;/em&gt; class instance (&lt;em&gt;locate.selector_name&lt;/em&gt;). We instantiate this class in the code as shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARt9yretvfEa_zGS6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARt9yretvfEa_zGS6.png" width="634" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below are the web actions that interact with the DOM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3268%2F0%2A86LA89sMg3fYRHiy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3268%2F0%2A86LA89sMg3fYRHiy.png" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Test Execution File
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from setup.setup import Settings
from conftest import admin
from sel_locators.sel_locators import Webactions
from django.contrib.auth.models import User

setUp = Settings()

blog = Webactions(setUp.driver)

class TestUserLoginFormSuccess(admin):

   def test_should_post_blog(self):
      setUp.setup()

      self.createSuperAdmin

      assert User.objects.count() == 1, "There should be only one superuser"

      blog.getWeb(self.live_server_url+'/login')

      assert "Log" in blog.getTitle(), "Error, log not in title"

      blog.fill_username('omisolaidowu')
      blog.fill_password('idowupaul')
      blog.submit_login()

      blog.getWeb(str(blog.current_url()))

      assert "Management" in blog.getTitle(), "Management must be on the next page"

      blog.published_yes()
      blog.enter_title("My First Blog")
      blog.write_content("Some lorem will be dumped here")
      blog.enter_description("Some blog descriptions")
      blog.submit_post()

      blog.getWeb(str(blog.current_url()))
      assert "Blog" in blog.getTitle(), "Blog must be on the next page"
      setUp.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We start the above test execution by importing the Settings class from the setup file, which we instantiate as setUp. The Webaction instance also uses the driver attribute from the setUp object to initiate a blog instance. Our test uses the User model from Django (imported from django.contrib.auth.models) to assert the number of superusers in the database. We also import the admin class from conftest.py.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AT7SOmC47gjf-5b6I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AT7SOmC47gjf-5b6I.png" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown previously, the admin class contains the fixture handler, which also inherits the &lt;em&gt;LiverServerTestCase *to pull a live server for local testing. So this allows the test runner class (*TestUserLoginFormSuccess&lt;/em&gt;) to inherit the admin and LiveServerTestCase classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7cxo7NDe73H51rQY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7cxo7NDe73H51rQY.png" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TestUserLoginForm has only one method (&lt;em&gt;test_should_post_blog&lt;/em&gt;) running the test steps. Pytest automatically looks for this test method in the test_module.py file to execute the Django test suite.&lt;/p&gt;

&lt;p&gt;That method starts by calling setUp.setup to maximize the browser window and initiate the Selenium WebDriver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdCCN_hZeqjPh3XnT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdCCN_hZeqjPh3XnT.png" width="484" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While you may not need to create a superuser in all Django test cases, only the superuser can access the editing engine in this case. So pytest needs the superuser credentials to log into the editor engine.&lt;/p&gt;

&lt;p&gt;But pytest runs an instance of the Django test. Thus, it can’t use the superuser credentials you create using the &lt;em&gt;python manage.py createsuperuser&lt;/em&gt; command. We need to create a dedicated superuser for our test — so it can access the admin panel and create a blog post.&lt;/p&gt;

&lt;p&gt;So for the superuser creation, we call the createSuperAdmin action. This comes from the &lt;strong&gt;super&lt;/strong&gt; fixture of the admin class inherited by the test runner class (&lt;em&gt;TestUserLoginFormSuccess&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXMKKLc_UildwAenR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXMKKLc_UildwAenR.png" width="600" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the superuser is created, the test leverages Django’s built-in User model to check if the superuser count in the database is more than one using pytest’s assert.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2616%2F0%2ALq1MNqyJvvHSr3Wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2616%2F0%2ALq1MNqyJvvHSr3Wb.png" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selenium runs through the test method in the test class to execute each test step. These steps come from the webAction class — instantiated as a blog. Hence, each test step comes from this instance as blog.test_step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, let’s go through each test step in the test_should_post_blog method.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; — Log on to the login page using the live_server_url attribute from Django’s LiveServerTestCase (inherited from the admin class). We also use pytest assert to check if a value exists in the page title.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2300%2F0%2Ae_xOer6fOZJa9OSC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2300%2F0%2Ae_xOer6fOZJa9OSC.png" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The live_server_url provides a default localhost port for testing in Django. When concatenated with another route in the app, it results in a complete web directory.&lt;/p&gt;

&lt;p&gt;For instance, [live_server_url+”/login”] might result in [&lt;a href="http://localhost:54776/login" rel="noopener noreferrer"&gt;http://localhost:54776/login&lt;/a&gt;]. The port number may vary, though. Checking one of our builds on the cloud grid shows that Django’s live_server_url runs on port 62409 for that instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2666%2F0%2A20CTKihU1lxUCZgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2666%2F0%2A20CTKihU1lxUCZgr.png" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned, this might change in another build. You don’t need to bother about how Django handles it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; — Fill in the username and password field with the superuser’s credentials. These credentials must match the ones used to create a superuser in this Django test. Otherwise, the test fails while trying to assert a value match on the following page.&lt;/p&gt;

&lt;p&gt;The test runs the following steps to fill out the login form with the superuser’s username and password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AWthgbZxAGEH3GPFc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AWthgbZxAGEH3GPFc.png" width="788" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; — Click the Login button to enter the post editor engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Amz1eTJBRukXfptd_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Amz1eTJBRukXfptd_.png" width="572" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once logged in, we expect to access the admin page, where the user can publish posts. You need to get the current URL to achieve this. To check if the test successfully navigates that page, we also assert that a value exists in its title.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2820%2F0%2A5xMlsz3nYe38iTP6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2820%2F0%2A5xMlsz3nYe38iTP6.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 4— Tick the Published checkbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApJ7gwWvg8D04rcij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApJ7gwWvg8D04rcij.png" width="672" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt; — Fill out the post and title fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2096%2F0%2A8wxsgbc3XMVMumrI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2096%2F0%2A8wxsgbc3XMVMumrI.png" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt; — Click Submit to publish the post and visit the homepage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AH7IHMJ_cIAAyBEa2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AH7IHMJ_cIAAyBEa2.png" width="572" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final stage in the test is to check successful URL navigation by asserting that a value exists in the homepage title.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2472%2F0%2ALoHGFBtStKJsjdRW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2472%2F0%2ALoHGFBtStKJsjdRW.png" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we close the browser instance and end the test using the tearDown method of the Settings class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AbIl14Z2RWV7OLIix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AbIl14Z2RWV7OLIix.png" width="528" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution of the locally hosted Django website
&lt;/h2&gt;

&lt;p&gt;To run the test, open the command line to your pytest Django project’s root folder and run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test runs successfully on the cloud grid as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3794%2F0%2Aqb3q8wKXnAL5ei34.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3794%2F0%2Aqb3q8wKXnAL5ei34.jpg" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In this Appium tutorial, learn about Appium and its benefits for mobile automation testing. Take a look at how Appium works and see how to perform &lt;a href="https://www.lambdatest.com/appium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Appium Automation &lt;/a&gt;testing of your mobile applications.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing hosted version of the Django application with pytest and Selenium
&lt;/h2&gt;

&lt;p&gt;While we’ve tested our Django website locally, you only require a few tweaks to make it reusable on a live website. The live demo version of the project is available at &lt;a href="https://django-app-selenium-pytest-test.vercel.app" rel="noopener noreferrer"&gt;https://django-app-selenium-pytest-test.vercel.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So you can access the login page at &lt;a href="https://django-app-selenium-pytest-test.vercel.app/login" rel="noopener noreferrer"&gt;https://django-app-selenium-pytest-test.vercel.app/login&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our previous test only assessed the login and post-publishing functionalities. While you don’t have permission to create a superuser for the live version, you can create one at &lt;a href="https://django-app-selenium-pytest-test.vercel.app/register" rel="noopener noreferrer"&gt;https://django-app-selenium-pytest-test.vercel.app/register&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then execute the test using the registered credentials.&lt;/p&gt;

&lt;p&gt;To repeat the test on the live version, you can separate the test folder from the pytest Django project and run the test independently.&lt;/p&gt;

&lt;p&gt;When extracted from the local Django project, the test folder looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2166%2F0%2A5JForfS0g3PvnZOL.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2166%2F0%2A5JForfS0g3PvnZOL.jpg" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While other files in the test directory remain the same, you’ll make some changes to &lt;em&gt;test_runner/test_module.py&lt;/em&gt; and &lt;em&gt;setup/setup.py&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Remove the tunnel option from desired_caps in the &lt;em&gt;setup file&lt;/em&gt;. Otherwise, the grid sees your build as coming from the local machine and fails the test.&lt;/p&gt;

&lt;p&gt;Below is how the new setup.py code looks.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from dotenv import load_dotenv
import os
load_dotenv('.env')

LT_USERNAME = os.getenv("LT_USERNAME")
LT_ACCESS_KEY = os.getenv("LT_ACCESS_KEY")

print(type(LT_ACCESS_KEY))
print(type(LT_USERNAME))


desired_caps = {
        'LT:Options' : {
            "user" : LT_USERNAME,
            "accessKey" : LT_ACCESS_KEY,
            "build" : "Django Functional Live Testing",
            "name" : "Django Live Test",
            "platformName" : "Windows 11",

        },
        "browserName" : "Chrome",
        "browserVersion" : "104.0",

    }


class Settings:

    def __init__(self) -&amp;gt; None:
        self.grid_url = "@hub.lambdatest.com/wd/hub"&amp;gt;https://{}:{}@hub.lambdatest.com/wd/hub".format(
            LT_USERNAME, LT_ACCESS_KEY
            )
        self.desired_caps = desired_caps
        self.driver = webdriver.Remote(command_executor=self.grid_url, desired_capabilities= self.desired_caps)

    def setup(self):
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
    def tearDown(self):
        try:
            if (self.driver != None):
                print("Cleaning the test environment")
                self.driver.quit()
        except  AssertionError as e:
            print(e)
            self.driver.quit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The desired_caps dictionary in this one doesn’t have a tunnel option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2312%2F0%2AFArs2PsKS0o-SP6V.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2312%2F0%2AFArs2PsKS0o-SP6V.png" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might not need a conftest.py file for the live test, as we only used that to create a superuser in our case. You also need to remove &lt;em&gt;LiveServerTestCase&lt;/em&gt; and the admin inheritance from the test runner class (&lt;em&gt;TestUserLoginFormSuccess&lt;/em&gt;) since the website is now live.&lt;/p&gt;

&lt;p&gt;Thus, the new &lt;em&gt;test_module.py&lt;/em&gt; file looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")
from setup.setup import Settings

from sel_locators.sel_locators import Webactions

setUp = Settings()


blog = Webactions(setUp.driver)

class TestUserLoginFormSuccess():

   def test_should_post_blog(self):
      setUp.setup()

      blog.getWeb('https://django-app-selenium-pytest-test.vercel.app/login')
      assert "Log" in blog.getTitle(), "Error, log not in title"

      blog.fill_username('registered username')
      blog.fill_password('registered password')
      blog.submit_login()

      blog.getWeb(str(blog.current_url()))

      assert "Management" in blog.getTitle(), "Management must be on the next page"

      blog.published_yes()
      blog.enter_title("My First Blog")
      blog.write_content("Some lorem will be dumped here")
      blog.enter_description("Some blog descriptions")
      blog.submit_post()

      blog.getWeb(str(blog.current_url()))
      assert "Blog" in blog.getTitle(), "Blog must be on the next page"
      setUp.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Live Test Execution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To run the live test, open your command prompt to the tests folder and run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The test runs on the cloud grid, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3790%2F0%2AMzQu_Ui8-V7jnzQU.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3790%2F0%2AMzQu_Ui8-V7jnzQU.jpg" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re looking to become an expert in automation testing and boost your Python skills, enrolling in a &lt;a href="https://www.lambdatest.com/certifications/selenium-python-101?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=certification" rel="noopener noreferrer"&gt;Selenium Python 101 certification&lt;/a&gt; program is an excellent first step. By doing this, you’ll lay a strong foundation for using Selenium Python in testing, paving the way for a successful career in this field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rounding Up: Simplify pytest Django UI automation testing with Selenium
&lt;/h2&gt;

&lt;p&gt;In this &lt;a href="https://www.lambdatest.com/learning-hub/selenium-pytest-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Selenium pytest tutorial&lt;/a&gt;, we looked into performing local testing of your website UI, which helps you assess its functionalities and discover bugs before deploying it to production.&lt;/p&gt;

&lt;p&gt;However, UI automation testing can be challenging without the appropriate tools to execute it. For versatile web frameworks like Django, pytest does the job excellently, as it fuses perfectly with Selenium and offers many built-in tools out of the box. Additionally, you can focus on writing your test script while pytest gives detailed information about your test execution.&lt;/p&gt;

&lt;p&gt;In addition to linking every test file without complexity, you’ve also seen the power of pytest in connecting your test suite to your Django project settings. Overall, automation UI testing of a locally hosted and live Django website on a Selenium cloud grid is easy with a few configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive User &lt;a href="https://www.lambdatest.com/learning-hub/user-acceptance-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=apr13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Acceptance Testing&lt;/a&gt; (UAT) tutorial that covers what User Acceptance Testing is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Can I use pytest with Django?
&lt;/h3&gt;

&lt;p&gt;Yes, you can use pytest with Django. In fact, pytest is a popular testing framework for Python, and many developers prefer using it over Django’s built-in testing framework.&lt;/p&gt;

&lt;p&gt;To use pytest with Django, you’ll need to install the pytest-django package, which provides many useful fixtures and plugins for testing Django applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Does Django use pytest or unittest?
&lt;/h3&gt;

&lt;p&gt;Django includes its testing framework called unittest (also known as django.test), which provides a set of tools and classes for writing and running tests. unittest is similar to Python’s built-in unittest module but with some added features specifically designed for testing Django applications.&lt;/p&gt;

&lt;p&gt;That being said, Django does not use pytest by default, but it can be used as an alternative testing framework instead of unittest. Many developers prefer using pytest over unittest because it offers a more concise and flexible syntax, powerful fixtures and plugins, and better test discovery mechanisms.&lt;/p&gt;

</description>
      <category>django</category>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>How To Generate Pytest Code Coverage Report</title>
      <dc:creator>Idowu Omisola</dc:creator>
      <pubDate>Mon, 13 Mar 2023 08:39:29 +0000</pubDate>
      <link>https://dev.to/testmuai/how-to-generate-pytest-code-coverage-report-3dl2</link>
      <guid>https://dev.to/testmuai/how-to-generate-pytest-code-coverage-report-3dl2</guid>
      <description>&lt;p&gt;The software quality level depends on how much you test. But it’s not unusual to miss some code parts or testing requirements during testing. This might result in bug or defect leakages if left unchecked. &lt;a href="https://www.lambdatest.com/blog/code-coverage-vs-test-coverage/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Code coverage&lt;/a&gt; helps you audit your test suite to determine which parts of your application are missing under test.&lt;/p&gt;

&lt;p&gt;Thus, you can be sure where your test covers. While using test coverage, you’ll get analytical insights about parts of your program that you’ve covered, those missed, and those you need to test. Code coverage is even easier with Python, considering Python’s simplicity.&lt;/p&gt;

&lt;p&gt;In this &lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; Python tutorial on pytest code coverage report, learn how to use code coverage with Python’s coverage.py using the pytest framework.&lt;/p&gt;

&lt;p&gt;So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Code Coverage?
&lt;/h2&gt;

&lt;p&gt;Code coverage is a simple statistic that measures the total lines of code that a &lt;a href="https://www.lambdatest.com/learning-hub/test-suite?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test suite &lt;/a&gt;validates. It uses set metrics to calculate the total number of lines of code in your application source code that runs successfully in a test — typically expressed as a percentage.&lt;/p&gt;

&lt;p&gt;Theoretically, you can calculate code coverage by dividing the total code lines that run under a test by the sum of the lines of code subjected to testing. Then multiply the result by 100 to get a percentage coverage.&lt;/p&gt;

&lt;p&gt;We can wrap this up using the simple mathematical equation below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code coverage&lt;/strong&gt; = (total code lines testedtotal code lines subjected to testing) 100&lt;/p&gt;

&lt;p&gt;For instance, testing a class containing 100 code lines in your source code involves subjecting the entire 100 lines of code to testing. If your test omits 40 lines of this class after testing, you can say your test suite has covered 60% of your code.&lt;/p&gt;

&lt;p&gt;In that case, the number of actual code lines tested was 60, whereas the number of lines exposed to testing was 100. There might be bugs buried within the 40 omitted lines you don’t want to slip through to production. You want to improve your test and source code to increase coverage in that case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is 100 Percent Code Coverage Possible?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s the thing: 100 percent code coverage isn’t enough reason to conclude that your application is free from bugs. For instance, you might still get 100% code coverage if you naively test functions, code lines, or components irrelevant to your app or its user story.&lt;/p&gt;

&lt;p&gt;While it can be time and resource-intensive, it’s best to improve your code consistently rather than aim for crisp 100% code coverage. The essence of code coverage is to expose underlying bugs and get more insights about what your test suite needs to cover. Invariably, it helps you improve your test reach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Our &lt;a href="https://www.lambdatest.com/learning-hub/gaming-platform-test-case-template?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Gaming Platform&lt;/a&gt; Test Case Templates tutorial offers a step-by-step guide for effective test scenarios. Improve your game’s quality and performance today.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Coverage vs. Test Coverage
&lt;/h2&gt;

&lt;p&gt;Many people, including testers and developers, use code and test coverage synonymously. But while these terms are closely related, there are still some differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Coverage
&lt;/h2&gt;

&lt;p&gt;Test coverage is a qualitative &lt;a href="https://www.lambdatest.com/learning-hub/black-box-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;black box validation&lt;/a&gt; of all the functionalities required to run an application smoothly. While analyzing this coverage type, you don’t need to understand the internal working mechanisms of the source code running the software under test.&lt;/p&gt;

&lt;p&gt;For example, your application design typically lists specific features it must satisfy to be fully functional. As a QA engineer, you want to ensure that your test suite covers all the required functionalities before you verify the software’s quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Coverage
&lt;/h2&gt;

&lt;p&gt;As explained, code coverage verifies the extent to which your test covers your source code. It’s a &lt;a href="https://www.lambdatest.com/learning-hub/white-box-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;white-box approach&lt;/a&gt; that requires you to understand the underlying mechanisms of the source code driving the application under test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Code Coverage
&lt;/h2&gt;

&lt;p&gt;Performing code coverage has many advantages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It helps audit your test suite and check test completeness.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It prevents defect or bug leakage, as it helps you find and fix bugs in your source code easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It helps discover missing requirements easily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It helps write better tests, increasing overall code quality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It helps track and assess underused or garbage functions that usually introduce bugs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It provides deeper code and user story insights and unveils more test cases, extending your test reach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It enhances final &lt;a href="https://www.lambdatest.com/learning-hub/software-quality?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;software quality&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Types of Code Coverage
&lt;/h2&gt;

&lt;p&gt;Code coverage can use a few different methods. We’ll discuss each below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branch Coverage
&lt;/h2&gt;

&lt;p&gt;Branch coverage validates whether a test covers the code execution path. It’s part of code coverage that checks whether each branch in your code, including loops and conditions, runs at least once during testing.&lt;/p&gt;

&lt;p&gt;Branch coverage is inclusive, as it seeks to leave no execution path unchecked. For instance, if you write a code that executes an action only if A &amp;gt; B, subjecting it to branch coverage first validates the condition (A &amp;gt; B). It then covers every statement (action) under that condition as well.&lt;/p&gt;

&lt;p&gt;However, your test doesn’t cover the code if the condition (A &amp;gt; B) is false. To capture the branch, you might need to run a test where the boolean condition returns both true and false. And that’s why you need a solid working knowledge of the source code or application during &lt;a href="https://www.lambdatest.com/learning-hub/unit-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;unit testing.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check out these top 50+ essential &lt;a href="https://www.lambdatest.com/learning-hub/mobile-development-test-case-template?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Mobile Development&lt;/a&gt; test cases to ensure your data’s integrity, accuracy, and consistency. Download our comprehensive template now&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Statement Coverage
&lt;/h2&gt;

&lt;p&gt;Statement coverage is more niche. Unlike branch coverage, it only validates the statements or actions within a code path. It doesn’t consider the parent code that prompts the execution of the action.&lt;/p&gt;

&lt;p&gt;It means if a test doesn’t cover the branch that determines an action execution (if branch coverage is zero), statement coverage for that branch is also zero.&lt;/p&gt;

&lt;p&gt;For example, if A &amp;gt; B is false, the branch statement (action) may not run under test. It’s safe to say statement coverage is partly dependent on branch coverage.&lt;/p&gt;

&lt;p&gt;But sometimes, a test might fail to cover the statements (actions) under a branch if it contains a bug somewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision Coverage
&lt;/h2&gt;

&lt;p&gt;Decision coverage is a subset of branch coverage that verifies if a test covers all the conditions in the source code. Unlike branch coverage, which validates all code paths, including loops, decision coverage only checks the boolean conditions that run during testing.&lt;/p&gt;

&lt;p&gt;Due to its design, decision coverage might omit false conditions, reducing the code coverage report.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loop Coverage
&lt;/h2&gt;

&lt;p&gt;Like decision coverage, loop coverage also falls under branch coverage. It validates the number (in percentage) of loops that run at least once under a test suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function Coverage
&lt;/h2&gt;

&lt;p&gt;Function coverage is the part of code coverage that evaluates the percentage of code functions that run during testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why pytest for Code Coverage Report?
&lt;/h2&gt;

&lt;p&gt;Pytest has plugins and supported modules for evaluating code coverage. Here are some reasons you want to use &lt;a href="https://www.lambdatest.com/blog/pytest-report-generation-for-selenium-automation-scripts/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;pytest for code coverage report generation&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It provides a straightforward approach for calculating coverage with a few lines of code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It features a couple of code coverage tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It gives comprehensive statistics of your code coverage score.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It features plugins that can help you prettify pytest code coverage reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It features a command-line utility for executing code coverage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It supports distributed and localized testing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that I have covered the basics of the pytest code coverage report, let me walk you through some of the tools used for the pytest code coverage report.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/UzkuOACmBpA"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;strong&gt;&lt;em&gt;&lt;a href="https://www.lambdatest.com/learning-hub/cms-test-case-template?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;CMS testing&lt;/a&gt; is required to ensure a content management system’s functionality, performance, security, and usability remain smooth.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools for Generating pytest Code Coverage Report
&lt;/h2&gt;

&lt;p&gt;Here are some of the most-used pytest code coverage tools.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;coverage.py&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The coverage.py library is one of the most-used pytest code coverage reporting tools. It’s a simple Python tool for producing comprehensive pytest code coverage reports in table format. You can use it as a command-line utility or plug it into your test script as an API to generate coverage analysis.&lt;/p&gt;

&lt;p&gt;The API option is recommended in case you need to prevent repeating a bunch of terminal commands each time you want to run the coverage analysis.&lt;/p&gt;

&lt;p&gt;While its command line utility might require a few patches to prevent reports from getting muffed, the API option provides clean, pre-styled HTML reports that you can view via a web browser.&lt;/p&gt;

&lt;p&gt;Below is the terminal line for executing code coverage with pytest using coverag.py.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coverage run -m pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above command runs all pytest test suites with names starting with “test.”&lt;/p&gt;

&lt;p&gt;All you need to do to generate reports while using its API is to specify a destination folder in your test code. It then overwrites the folder’s HTML report in subsequent tests.&lt;/p&gt;

&lt;p&gt;You’ll see its API usage as you read further through the code coverage demonstration section.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pytest-cov&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;pytest-cov is a code coverage plugin and command line utility for pytest. It also provides extended support for coverage.py.&lt;/p&gt;

&lt;p&gt;Like coverage.py, you can use it to generate XML or HTML reports and view a pretty code coverage analysis via the browser. Although using pytest-cov involves running a simple command via the terminal, the terminal command becomes longer and more complex as you add more coverage options.&lt;/p&gt;

&lt;p&gt;For instance, generating a command-line-only report is as simple as running the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest --cov
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The result of the pytest –cov command is below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpyoyjonqxrc84kpu1k7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpyoyjonqxrc84kpu1k7.jpg" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But generating an HTML report requires additional command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest --cov --cov-report=html:coverage_re
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Where coverage_re is the coverage report directory.&lt;/p&gt;

&lt;p&gt;Below is the report when viewed via the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3800%2F0%2Ay51BJE-oE6FtnQSM.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3800%2F0%2Ay51BJE-oE6FtnQSM.jpg" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a list of widely-used command line options with –cov:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
    &lt;tr&gt;
        &lt;td&gt;–COV OPTIONS&lt;/td&gt;
        &lt;td&gt;null&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;-cov=PATH&lt;/td&gt;
        &lt;td&gt;Measure coverage for a filesystem path. (multi-allowed)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-report=type&lt;/td&gt;
        &lt;td&gt;To specify the type of report to generate. Type can be HTML, XML, annotate, term, term-missing, or lcov. term, term- missing may be followed by “:skip-covered”. annotate, html, xml, and lcov may be followed by “:DEST” where DEST specifies the output location.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-config=path&lt;/td&gt;
        &lt;td&gt;Config file for coverage. Default: .coveragerc&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–no-cov-on-fail&lt;/td&gt;
        &lt;td&gt;Do not report coverage if the test fails. Default: False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–no-cov&lt;/td&gt;
        &lt;td&gt;Disable coverage report completely (useful for debuggers). Default: False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-reset&lt;/td&gt;
        &lt;td&gt;Reset cov sources accumulated in options so far. Mostly useful for scripts and configuration files.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-fail-under=MIN&lt;/td&gt;
        &lt;td&gt;Fail if the total coverage is less than MIN.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-append&lt;/td&gt;
        &lt;td&gt;Do not delete coverage but append to current. Default: False&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-branch&lt;/td&gt;
        &lt;td&gt;Enable branch coverage.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;–cov-context&lt;/td&gt;
        &lt;td&gt;Choose the method for setting the dynamic context.&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Code Coverage Demonstration using coverage.py
&lt;/h2&gt;

&lt;p&gt;The code coverage demonstration for this blog includes a test for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A plain name tweaker class example to show why you may not achieve 100% code coverage and how you can use its result to extend your test reach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Registration steps code coverage demonstration using the &lt;a href="https://ecommerce-playground.lambdatest.io/index.php?route=account/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest eCommerce Playground&lt;/a&gt;, executed on the cloud grid.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll use Python’s coverage module, coverage.py, to demonstrate the code coverage for all the tests in this tutorial on the pytest code coverage report. So you need to install the coverage.py module since it’s third-party. You’ll also need to install the &lt;a href="https://www.lambdatest.com/blog/selenium-webdriver-tutorial-with-examples/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium WebDriver&lt;/a&gt; (to access web elements) and python-dotenv (to mask your secret keys).&lt;/p&gt;

&lt;p&gt;Create a &lt;em&gt;requirements.txt&lt;/em&gt; file in your project root directory and insert the following packages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coverage
selenium
python-dotenv
pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, install the packages using pip:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command installs the required packages as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AG4D84qJRL5WhWq6M.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AG4D84qJRL5WhWq6M.jpg" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned, coverage.py lets you generate and write coverage reports inside an HTML file and view it in the browser. You’ll see how to do this later.&lt;/p&gt;

&lt;p&gt;Below is a screenshot of the project structure inside VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2504%2F0%2ABY3vuG771ms2tJzR.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2504%2F0%2ABY3vuG771ms2tJzR.jpg" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;locators&lt;/em&gt; folder contains the web locator for the LambdaTest playground test. However, the plain_test folder contains the test class for the example name tweaking scenario.&lt;/p&gt;

&lt;p&gt;The run_coverage folder holds the test runners for the entire test suite. It also contains a dedicated folder for storing the auto-generated coverage reports.&lt;/p&gt;

&lt;p&gt;The setup directory is the LamdaTest grid setup for the registration steps test case. And finally, the test scenario directory contains the file with the class that executes the web actions in locators.py.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Streamline your mobile app testing process with our tutorial on &lt;a href="https://www.lambdatest.com/learning-hub/xamarin-test-case-template?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Xamarin Test Case Templates&lt;/a&gt;. Learn how to create comprehensive test cases efficiently.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Code Coverage helps you extend your test reach: Name Tweaker Class Test Example
&lt;/h2&gt;

&lt;p&gt;We’ll start by considering an example test for the name tweaking class to demonstrate why you may not achieve 100% code coverage. And you’ll also see how to extend your code coverage.&lt;/p&gt;

&lt;p&gt;The name tweaking class contains two methods. One is for concatenating a new and an old name, while the other is for changing an existing name.&lt;/p&gt;

&lt;p&gt;For this example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class test_should_tweak_name:
    def __init__(self, name) -&amp;gt; None:
        self.name = name

    def test_should_addNames(self, name):
        if self.name == "LambdaTest":
            new_name = self.name+" "+name
            assert new_name == "LambdaTest Grid", "new_name should be LambdaTest Grid"
            return new_name
        else:
            return self.name

    def test_should_changeName(self, name):
        self.name = name
        assert self.name == "LambdaTest Cloud Grid", "new_name should be LambdaTest Cloud Grid"
        return name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To execute the test and get code coverage less than 100%, we’ll start by omitting a test case for the else statement in the first method and also ignore the second method entirely (test_should_changeName).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import the Pytest coverage plugin:
import coverage

# Start code coverage before importing other modules:
cov = coverage.Coverage()
cov.start()

# Main code to be covered----------:

import sys
sys.path.append(sys.path[0] + "/..")

from plain_tests.plain_tests import test_should_tweak_name

tweak_names = test_should_tweak_name("LambdaTest")
print(tweak_names.test_should_addNames("Grid"))

cov.stop()
cov.save()
cov.html_report(directory='coverage_reports')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run the test by running the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run_coverage/name_tweak_coverage.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The coverage generates a report folder like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2064%2F0%2Ars703dbnwQtu7j2F.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2064%2F0%2Ars703dbnwQtu7j2F.jpg" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go into the coverage_reports folder and run index.html via your browser. The test yields 69% coverage (as shown below) since it omits the two named instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A67uUc090AOFlXVvO.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A67uUc090AOFlXVvO.jpg" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s extend the code coverage:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Although we’ve deliberately ignored the second method in that class, it was easy to forget to include a case for the else statement in the test. That’s because we only focused on validating the true condition. Including a test case that assumes negativity (where the condition returns false) extends the code coverage.&lt;/p&gt;

&lt;p&gt;So what if we add a test case for the second method and another one that assumes that the supplied name in the first method isn’t LambdaTest?&lt;/p&gt;

&lt;p&gt;The code coverage yields 100% since we’re considering all possible scenarios for the class under test.&lt;/p&gt;

&lt;p&gt;So a more inclusive test looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import the Pytest coverage plugin:
import coverage

# Start code coverage before importing other modules:
cov = coverage.Coverage()
cov.start()

# Main code to be covered----------:

import sys
sys.path.append(sys.path[0] + "/..")

from plain_tests.plain_tests import test_should_tweak_name


tweak_names = test_should_tweak_name("LambdaTest")

will_not_tweak_names = test_should_tweak_name("Not LambdaTest")

print(tweak_names.test_should_addNames("Grid"))

print(tweak_names.test_should_changeName("LambdaTest Cloud Grid"))

print(will_not_tweak_names.test_should_addNames("Grid"))


# Stop code coverage and save the output in a reports directory---------:
cov.stop()
cov.save()
cov.html_report(directory='coverage_reports')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Adding the will_not_tweak_names variable covers the else condition in the test. Additionally, calling test_should_changeName from the class instance captures the second method in that class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2624%2F0%2AKb2kuR8UwBu1qcSp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2624%2F0%2AKb2kuR8UwBu1qcSp.png" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extending the coverage this way generates 100% code coverage, as seen below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ap93gXYaDo7ZEV5mU.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ap93gXYaDo7ZEV5mU.jpg" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement Code Coverage on the Cloud Grid?
&lt;/h2&gt;

&lt;p&gt;We’ll build on the previous code structure for this test demo. Here, we’ll write test cases for the registration web actions on the LambdaTest eCommerce Playground. Then we’ll run the test on the LambdaTest cloud grid based on these actions without supplying some parameters; this might involve failure to fill in some form fields or submitting an invalid email address.&lt;/p&gt;

&lt;p&gt;LambdaTest is a cloud-based continuous quality platform that enables you to conduct &lt;a href="https://www.lambdatest.com/python-automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Python automation testing&lt;/a&gt; on a dependable and scalable online Selenium Grid infrastructure, spanning over 3000 real web browsers and operating systems. Additionally, it offers parallel test execution that can significantly reduce your build times while performing &lt;a href="https://www.lambdatest.com/python-web-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Python web automation.&lt;/a&gt;&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/WZlsHlReRww"&gt;
&lt;/iframe&gt;
&lt;br&gt;
You can also Subscribe to the &lt;a href="https://www.youtube.com/channel/UCCymWVaTozpEng_ep0mdUyw?sub_confirmation=1?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=youtube" rel="noopener noreferrer"&gt;LambdaTest YouTube Channel &lt;/a&gt;and stay updated with the latest tutorials around &lt;a href="https://www.lambdatest.com/automated-browser-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated browser testing,&lt;/a&gt; &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Cypress E2E testing&lt;/a&gt;, CI/CD, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Discover the top 60 essential &lt;a href="https://www.lambdatest.com/learning-hub/healthcare-domain-test-case-examples?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Healthcare Domain Testing&lt;/a&gt; Test Cases along with its importance, types and usage for better understanding.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We’ll compute the code coverage under the following test scenarios:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Submit the registration form with an invalid email address and missing fields.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Submit the form with all fields filled appropriately (successful registration).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll also see how adding the missing parameters can extend the code coverage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the test environment
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver

from dotenv import load_dotenv
import os
load_dotenv('.env')

LT_GRID_USERNAME = os.getenv("LT_GRID_USERNAME")
LT_ACCESS_KEY = os.getenv("LT_ACCESS_KEY")

desired_caps = {
        'LT:Options' : {
            "user" : os.getenv("LT_GRID_USERNAME"),
            "accessKey" : os.getenv("LT_ACCESS_KEY"),
            "build" : "Test Coverage Idowu",
            "name" : "Firefox coverage demo2",
            "platformName" : os.getenv("TEST_OS")
        },
        "browserName" : "FireFox",
        "browserVersion" : "103.0",
    }
gridURL = "@hub.lambdatest.com/wd/hub"&amp;gt;https://{}:{}@hub.lambdatest.com/wd/hub".format(LT_GRID_USERNAME, LT_ACCESS_KEY)

class testSettings:

    def __init__(self) -&amp;gt; None:
        self.driver = webdriver.Remote(command_executor=gridURL, desired_capabilities= desired_caps)

    def testSetup(self):
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
    def tearDown(self):
        if (self.driver != None):
            print("Cleaning the test environment")
            self.driver.quit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Code Walkthrough
&lt;/h2&gt;

&lt;p&gt;First, import the Selenium WebDriver to configure the test driver. Get your grid username and access key (passed as LT_GRID_USERNAME and LT_GRID_ACCESS_KEY, respectively) from the cloud grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2AXM80SNYEeWdX9fo6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2068%2F0%2AXM80SNYEeWdX9fo6.png" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The desired_caps is a dictionary of the desired capabilities for the test suite. It details your username, access key, browser name, version, build name, and platform type that runs your driver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2252%2F0%2ARiBgy0A6CNdN5Pnd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2252%2F0%2ARiBgy0A6CNdN5Pnd.png" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next is the grid URL. We access this using the access key and username declared earlier. We then pass this URL and the desired capability into the driver attribute inside the &lt;strong&gt;init&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A1YNAQWqmIMYFKl_E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A1YNAQWqmIMYFKl_E.png" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Write a &lt;em&gt;testSetup&lt;/em&gt; method that initiates the test suite. It works by using the implicitly_wait function to pause for the DOM to load elements. It then uses the &lt;em&gt;maximize_window&lt;/em&gt; method to expand the chosen browser frame.&lt;/p&gt;

&lt;p&gt;However, the &lt;em&gt;tearDown&lt;/em&gt; method helps stop the test instance and closes the browser using the quit method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2008%2F0%2AVUtV63jwbdGJWVgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2008%2F0%2AVUtV63jwbdGJWVgr.png" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get your LambdaTest username and access key, go to the &lt;a href="https://automation.lambdatest.com/build?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest Builds Section&lt;/a&gt; of your dashboard and click Access Key at the top right to display this information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AU3P9I1ATZUJfx4A3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AU3P9I1ATZUJfx4A3.jpg" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;from selenium.webdriver.common.by import Byfrom &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

class element_locator:
    first_name = "//input[@id='input-firstname']"
    last_name = "//input[@id='input-lastname']"
    email = "//input[@id='input-email']"
    telephone = "//input[@id='input-telephone']"
    password = "//input[@id='input-password']"
    confirm_password = "//input[@id='input-confirm']"
    subscribe_no = "//label[@for='input-newsletter-no']"
    agree_terms = "//label[@for='input-agree']"
    submit = "//input[@value='Continue']"
    error_message = "//div[@class='text-danger']"

locator = element_locator()

class registerUser:
    def __init__(self, driver) -&amp;gt; None:
        self.driver=driver
    def error_message(self):  
        try:
            return self.driver.find_element(By.XPATH, locator.error_message).is_displayed()
        except NoSuchElementException:
            print("All code in registration test covered")

    def test_getWeb(self, URL):
        self.driver.get(URL)

    def test_getTitle(self):
        return self.driver.title
    def test_fillFirstName(self, data):
        self.driver.find_element(By.XPATH, locator.first_name).send_keys(data)
    def test_fillLastName(self, data):
        self.driver.find_element(By.XPATH, locator.last_name).send_keys(data)
    def test_fillEmail(self, data):
        self.driver.find_element(By.XPATH, locator.email).send_keys(data)
    def test_fillPhone(self, data):
        self.driver.find_element(By.XPATH, locator.telephone).send_keys(data)
    def test_fillPassword(self, data):
        self.driver.find_element(By.XPATH, locator.password).send_keys(data)
    def test_fillConfirmPassword(self, data):
        self.driver.find_element(By.XPATH, locator.confirm_password).send_keys(data)
    def test_subscribeNo(self):
        self.driver.find_element(By.XPATH, locator.subscribe_no).click()
    def test_agreeToTerms(self):
        self.driver.find_element(By.XPATH, locator.agree_terms).click()
    def test_submit(self):
        self.driver.find_element(By.XPATH, locator.submit).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Start by importing Selenium By object into the file to declare the locator pattern for the DOM. We’ll use the &lt;em&gt;NoSuchElementException&lt;/em&gt; to check for an error message in the DOM (in case of invalid inputs). To learn more about it, go through this tutorial on &lt;a href="https://www.lambdatest.com/blog/handling-errors-and-exceptions-in-selenium-python/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;handling errors and exceptions in Selenium Python.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, declare a class to hold the web elements. Then create another class to handle the web actions for the registration form.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;element_selector&lt;/em&gt; class contains the web element locations. Each uses the &lt;a href="https://www.lambdatest.com/blog/complete-guide-for-using-xpath-in-selenium-with-examples/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;XPath locator.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2344%2F0%2AtwKANYCYM-fksFlx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2344%2F0%2AtwKANYCYM-fksFlx.png" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;registerUser&lt;/em&gt; class accepts the driver attribute to initiate web actions. You’ll get the driver attribute from the setup class while instantiating the &lt;em&gt;registerUser&lt;/em&gt; class.&lt;/p&gt;

&lt;p&gt;The error_message method inside the &lt;em&gt;registerUser&lt;/em&gt; class does two things. First, it checks for invalid field error messages in the DOM when the test tries to submit the registration form with unacceptable inputs. The check runs every time inside a try block. So the test covers it regardless.&lt;/p&gt;

&lt;p&gt;Secondly, it runs the code in the try block if it finds an input error message element in the DOM. This prevents the except block from running, flagging it as non-covered code.&lt;/p&gt;

&lt;p&gt;Otherwise, Selenium raises a &lt;em&gt;NoSuchElementException&lt;/em&gt;. This forces the test to log the print in the except block and mark it as covered code. This feels like a reverse strategy. But it helps code coverage capture more scenarios.&lt;/p&gt;

&lt;p&gt;So besides capturing omitted fields (web action methods not included in the &lt;a href="https://www.lambdatest.com/learning-hub/test-execution?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;test execution&lt;/a&gt;), it ensures that the test accounts for an invalid email address or empty string input.&lt;/p&gt;

&lt;p&gt;Thus, if the error message is displayed in the DOM, the method returns the error message element. Otherwise, Selenium raises a &lt;em&gt;NoSuchElementException&lt;/em&gt;, forcing the test to log the printed message, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2932%2F0%2AKB35_nQ0nh09Getu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2932%2F0%2AKB35_nQ0nh09Getu.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rest of the class methods are web action declarations for the locators in the &lt;em&gt;element_locator&lt;/em&gt; class. Excluding the fields that require a click action, the other class methods accept a data parameter, a string that goes into the input fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Abo3OU8O8mKJgpdrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Abo3OU8O8mKJgpdrq.png" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s run each test scenario to see its computed code coverage.&lt;/p&gt;

&lt;p&gt;But first, create a test runner file for the code coverage scenarios. You’ll execute this file to run the test and calculate the code coverage.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import the Pytest coverage plugin:
import coverage

# Start code coverage before importing other modules:
cov = coverage.Coverage()
cov.start()

# Main code to be covered----------:

import sys
sys.path.append(sys.path[0] + "/..")
from testscenario.scenarioRun import test_registration

registration = test_registration()
registration.it_should_register_user()

# Stop code coverage and save the output in a reports directory---------:
cov.stop()
cov.save()
cov.html_report(directory='coverage_reports')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code starts by importing the coverage module. Next, declare an instance of the Coverage class and call the start method at the top of the code. Once code coverage begins, import the &lt;em&gt;test_registration&lt;/em&gt; class from scenarioRun.py. Instantiate the class as registration.&lt;/p&gt;

&lt;p&gt;The class method, it_should_register_user is a test method that executes the test case (you’ll see this class in the next section). Use &lt;em&gt;cov.stop()&lt;/em&gt; to close the code coverage process. Then use cov.save() to capture the coverage report.&lt;/p&gt;

&lt;p&gt;The cov.html_report method writes the coverage result into an HTML file inside the declared directory &lt;em&gt;(coverage_reports)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And running this file executes the test and coverage report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now let’s tweak the web action methods inside scenarioRun.py to see the difference in code coverage for each scenario.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1:&lt;/strong&gt; Submit the registration form with an invalid email address and some missing fields.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")

from locators.locator import registerUser
from setup.setup import testSettings
import unittest
from dotenv import load_dotenv
import os

load_dotenv('.env')

setup = testSettings()

test_register = registerUser(setup.driver)

E_Commerce_palygroud_URL = "https:"+os.getenv("E_Commerce_palygroud_URL")

class test_registration(unittest.TestCase):

    def it_should_register_user(self):
        setup.testSetup()
        test_register.test_getWeb(E_Commerce_palygroud_URL)
        title = test_register.test_getTitle()

        self.assertIn("Register", title, "Register is not in title")

        test_register.test_fillEmail("testrs@gmail")

        test_register.test_fillPhone("090776632")
        test_register.test_fillPassword("12345678")
        test_register.test_fillConfirmPassword("12345678")

        test_register.test_submit()

        test_register.error_message()

        setup.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Pay attention to the imported built-in and third-party modules. We start by importing the registerUser and testSettings classes we wrote earlier. The &lt;em&gt;testSettings&lt;/em&gt; class contains the &lt;em&gt;testSetup()&lt;/em&gt; and &lt;em&gt;tearDown()&lt;/em&gt; methods for setting up and closing the test respectively. We instantiate this class as a setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2868%2F0%2ASsxadxkEptCifxcn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2868%2F0%2ASsxadxkEptCifxcn.png" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As seen below, the registerUser class instantiates as test_register using the setup’s driver attribute. We also need the unittest’s assert function. So we import that at the top level as well. The dotenv package lets you get the test website’s URL from the environment variable.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;test.testSetup&lt;/em&gt; method initiates the test case (it_should_registerUser method) and prepares the test environment. Next, we launch the website using the &lt;em&gt;test_getWeb&lt;/em&gt; method. This accepts the website URL declared earlier. The inherited property from the unittest test, &lt;em&gt;assertIn&lt;/em&gt;, checks whether the declared string is in the title. Use the setup.tearDown to close the browser and clean the test environment.&lt;/p&gt;

&lt;p&gt;As earlier stated, the rest of the test case omits some methods from the &lt;em&gt;registerUser&lt;/em&gt; class to see its effect on code coverage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2712%2F0%2AKuJXGlY1G_qWOaKq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2712%2F0%2AKuJXGlY1G_qWOaKq.png" width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1 code coverage execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To execute the test and code coverage, cd into the test_run_coverage folder and run the run_coverage.py file using &lt;strong&gt;pytest:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the code runs successfully, open the coverage_reports folder and open the index.html file via a browser. The code coverage reads 94%, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A5gNqL_v4W_Ojhp6n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A5gNqL_v4W_Ojhp6n.jpg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although the other test files read 100%, locator.py has 89% of its code covered, reducing the overall score to 94%. This is because we omitted some web actions and filled in an invalid email address while running the test.&lt;/p&gt;

&lt;p&gt;Opening locator.py gives more insights into the missing steps (highlighted in red), as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Apa64xLYAKAnNy2h2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Apa64xLYAKAnNy2h2.jpg" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although you might expect the coverage to flag the test_fillEmail method, it doesn’t because the test provided an email address; it was only invalid. The except block is the invalid parameter indicator. And it only runs if the input error message element isn’t in the DOM.&lt;/p&gt;

&lt;p&gt;As seen, the test flags the except block this time since the input error message appears in the DOM due to invalid entries.&lt;/p&gt;

&lt;p&gt;The test suite runs on the cloud grid with some red flags in the test video, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A1SAB3PNE55zFRjkY.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A1SAB3PNE55zFRjkY.jpg" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2:&lt;/strong&gt; Submit the form with all fields filled appropriately (successful registration).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
sys.path.append(sys.path[0] + "/..")

from locators.locator import registerUser
from setup.setup import testSettings
import unittest
from dotenv import load_dotenv
import os

load_dotenv('.env')

setup = testSettings()

test_register = registerUser(setup.driver)

E_Commerce_palygroud_URL = "https:"+os.getenv("E_Commerce_palygroud_URL")

class test_registration(unittest.TestCase):


    def it_should_register_user(self):

        setup.testSetup()
        test_register.test_getWeb(E_Commerce_palygroud_URL)
        title = test_register.test_getTitle()

        self.assertIn("Register", title, "Register is not in title")

        test_register.test_fillFirstName("Idowu")
        test_register.test_fillLastName("Omisola")

        test_register.test_fillEmail("testrs@gmail.com")

        test_register.test_fillPhone("090776632")
        test_register.test_fillPassword("12345678")
        test_register.test_fillConfirmPassword("12345678")
        test_register.test_subscribeNo()
        test_register.test_agreeToTerms()
        test_register.test_submit()

        test_register.error_message()

        setup.tearDown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Scenario 2 has a similar code structure and naming convention to scenario 1. However, we’ve expanded the test reach to cover all test steps in scenario 2. Import the needed modules as in the previous scenario. Then instantiate the testSettings and registerUser classes as setup and test_register, respectively.&lt;/p&gt;

&lt;p&gt;To get an inclusive test suit, ensure that you execute all the test steps from the registerUser class, as shown below. We expect this to generate 100% code coverage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2588%2F0%2AqinAcjWKQcMm31uI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2588%2F0%2AqinAcjWKQcMm31uI.png" width="800" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2 code coverage execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go into the run_coverage folder and run the &lt;strong&gt;pytest&lt;/strong&gt; command to execute the &lt;em&gt;test_run_coverage.py file&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open the index.html file inside the coverage reports via a browser to see your pytest code coverage report. It’s now 100%, as shown below. This means the test doesn’t omit any web action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ALTQ_E6pz6EBwgaCS.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ALTQ_E6pz6EBwgaCS.jpg" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the test suite execution on the cloud grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ACnE1m4Ld3WNf7_Wn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ACnE1m4Ld3WNf7_Wn.jpg" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re aiming to develop expertise in &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt; and enhance your skills in Python, pursuing a Selenium Python 101 certification can be a great starting point. Doing so can establish a solid base in utilizing Selenium Python for testing, setting you on the path to a thriving career in this domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Here you will get to know about what is insurance domain and how it works. further, we have included all major and miscellaneous test cases, which every tester should verify during &lt;a href="https://www.lambdatest.com/learning-hub/insurance-domain-testing-test-cases?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;insurance domain testing&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Manually auditing your test suite can be an uphill battle, especially if your application code base is large. While performing &lt;a href="https://www.lambdatest.com/selenium-python-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=mar13_bh&amp;amp;utm_term=bh&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium Python testing&lt;/a&gt;, leveraging a dedicated code coverage tool boosts your productivity, as it helps you flag untested code parts to detect potential bugs easily. Although you’ll still need human inputs to decide your test requirements and coverage, performing a code coverage analysis gives you clear direction.&lt;/p&gt;

&lt;p&gt;As you’ve seen, Python even brings further simplicity to code coverage with detailed human-friendly reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. How do I create a Pytest code coverage report?
&lt;/h3&gt;

&lt;p&gt;Pytest is a popular testing framework for Python, and it includes a built-in plugin for generating coverage reports called pytest-cov. You can customize the coverage report by passing additional options to pytest-cov, such as ignoring certain files or setting a minimum coverage threshold.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. What is code coverage in Python Pytest?
&lt;/h3&gt;

&lt;p&gt;Code coverage measures how much of your code is executed during automated tests. In the context of Python and pytest, code coverage refers to the percentage of code lines that are executed during tests.&lt;/p&gt;

&lt;p&gt;Pytest has a built-in coverage plugin, pytest-cov, that can measure code coverage during testing. When you run your tests with pytest-cov, it tracks which lines of code are executed during the tests and generates a report showing the coverage percentage for each file.&lt;/p&gt;

</description>
      <category>python</category>
      <category>productivity</category>
      <category>testing</category>
      <category>security</category>
    </item>
    <item>
      <title>Playwright Python Tutorial: Getting Started With Python End To End Testing</title>
      <dc:creator>Idowu Omisola</dc:creator>
      <pubDate>Wed, 21 Dec 2022 22:33:31 +0000</pubDate>
      <link>https://dev.to/testmuai/playwright-python-tutorial-getting-started-with-python-end-to-end-testing-27bk</link>
      <guid>https://dev.to/testmuai/playwright-python-tutorial-getting-started-with-python-end-to-end-testing-27bk</guid>
      <description>&lt;p&gt;It’s essential to test all components of your website to see if they work as expected. &lt;a href="https://www.lambdatest.com/blog/playwright-end-to-end-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Playwright’s end to end testing&lt;/a&gt; capability helps you achieve this easily. However, if you’re comfortable using Python, you can pair it with the &lt;a href="https://www.lambdatest.com/playwright-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Playwright testing&lt;/a&gt; framework to run Python end to end testing on your website.&lt;/p&gt;

&lt;p&gt;The Playwright testing framework is more straightforward and lightweight than most alternatives, including &lt;a href="https://www.lambdatest.com/learning-hub/cypress-tutorial?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; and &lt;a href="https://www.lambdatest.com/testcafe?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;TestCafe&lt;/a&gt;, among many others. To give it a boost, it also offers &lt;a href="https://www.lambdatest.com/blog/everything-you-need-to-know-about-api-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;API testing&lt;/a&gt;. Hence, it’s an excellent choice for end to end testing.&lt;/p&gt;

&lt;p&gt;In this Playwright Python tutorial, you’ll learn how to combine Python’s simplicity with Playwright’s utility for end to end testing. But let’s start by understanding end to end testing and why you want to use Playwright to execute your test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is End to End Testing?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/learning-hub/end-to-end-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;End to end testing&lt;/a&gt; is a method that validates the entire usage flow of an application to ensure that every part of it works as expected. It involves paying attention to every detail and extending the &lt;a href="https://www.lambdatest.com/blog/code-coverage-vs-test-coverage/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test coverage&lt;/a&gt; to discover and fix bugs. Its ultimate goal is to help you build a bug-free site.&lt;/p&gt;

&lt;p&gt;Hence, it’s an adopted methodology for testing complex websites. Generally, it involves picking up your website’s user story and simulating your users’ behavior in different integration environments.&lt;/p&gt;

&lt;p&gt;During end to end testing, you want to consider operating system and browser variability, among many other factors determining an app’s viability. Therefore, it involves conducting a critically inclusive test — from the back (API testing) to the front end.&lt;/p&gt;

&lt;p&gt;With that in mind, automated end to end testing reduces testing costs, improves application integrity, and helps your product ship faster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Apfbpkw2h60v0dEzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Apfbpkw2h60v0dEzb.png" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Playwright?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.lambdatest.com/playwright?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;, released by Microsoft in 2020, is an open-source, cross-platform &lt;a href="https://www.lambdatest.com/blog/best-test-automation-frameworks-2021/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automation testing framework&lt;/a&gt;. It supports many browsers, including Chromium, Firefox, and Microsoft Edge, as well as WebKit-based applications. So it provides a handy toolkit for testing web and mobile applications.&lt;/p&gt;

&lt;p&gt;It also works with most modern programming languages. As of writing, it supports JavaScript, Python, TypeScript, .NET, and Java. This Playwright Python tutorial will look into how to perform end to end tests with Playwright using Python.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wawbt1cATsk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Playwright for Python end to end testing?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.lambdatest.com/blog/playwright-framework/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Playwright framework&lt;/a&gt; has many event igniters that let you interact with different client-side features of your website like a real user. And it plays well with both synchronous and asynchronous requests. Thus, you can choose to run your test sequentially or leverage the power of Python’s &lt;strong&gt;asyncio **package to run test steps concurrently using **async/await&lt;/strong&gt;. The latter is handy for interacting with websites that run tasks asynchronously.&lt;/p&gt;

&lt;p&gt;Its API testing capability also helps you validate requests and responses on your app’s endpoints.&lt;/p&gt;

&lt;p&gt;Depending on the specified test browser, the Playwright also isolates each test per browser. Thus, each test case in Playwright is a browser context, which defines a browser instance generated rapidly to reduce overhead.&lt;/p&gt;

&lt;p&gt;Considering Playwright’s versatile utility and Python’s simplicity and acceptance, combining both to write your test script eases automation testing. Besides, the 2021 Stackoverflow Developer Survey puts Python in third place among the most used programming languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ABJyj1NV7oycuTu5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ABJyj1NV7oycuTu5p.png" width="800" height="815"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Playwright framework is popular, with over 2,000 forks and over 41,800 stars on GitHub. And what’s more? It also has fair enough mentions on Stack Overflow with a good community. So you can always get help resolving bugs in your tests.&lt;/p&gt;

&lt;p&gt;Unlike &lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;, where you might have to define custom timeout intervals to prevent false failure if elements fail to load, Playwright has an auto-wait feature that tentatively pauses for DOM elements to load before executing further steps in the test case. This wait time defaults to 30 seconds before it times out, but you can extend this using Playwright’s built-in &lt;strong&gt;wait_for_timeout()&lt;/strong&gt; function. Hence, you’ll have a lower false failure probability with Playwright.&lt;/p&gt;

&lt;p&gt;Playwright also provides an inspector tool, which you can use to generate selectors easily as you write your test. This helps reduce or even eliminate the need to inspect the browser manually.&lt;/p&gt;

&lt;p&gt;Its code generator works in a play-and-record fashion. You can use it to spin up your app’s UI and auto-generate test scripts in any language as you interact with the DOM. Although this might be handy if you’re unfamiliar with coding, it’s less customizable. It doesn’t suit complex websites (e.g., e-commerce, banking, fintech, and more), as the code generated is often lengthy and complex.&lt;/p&gt;

&lt;p&gt;These features, coupled with its intuitive selector and locator classes, make Playwright an excellent end to end testing framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright GitHub trends as of writing this Playwright Python tutorial:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Stars: 41.8k&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Used by: 14.1k&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forks: 2k&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watchers: 360&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contributors: 274&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Releases: 79&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we deep dive into this Playwright Python tutorial, let’s see how to install Playwright for Python end to end testing and set up the test project.&lt;/p&gt;

&lt;p&gt;Run Automated Playwright Python Tests Online. &lt;a href="https://accounts.lambdatest.com/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=register" rel="noopener noreferrer"&gt;Try LambdaTest Now!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: &lt;a href="https://www.lambdatest.com/learning-hub/data-driven-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Data Driven Testing&lt;/a&gt;: A Comprehensive Guide With Examples and Best Practices&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup Playwright for Python end to end testing?
&lt;/h2&gt;

&lt;p&gt;You have to install and set up your computer to start using Playwright Python for &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automation testing&lt;/a&gt;. However, this Playwright Python tutorial assumes that your machine runs on Python 3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install Python’s latest version.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to the official Python website to download and install the latest version of Python on your machine.&lt;/p&gt;

&lt;p&gt;The Windows OS doesn’t come with Python by default, so you’ll have to install it explicitly. However, ensure that you allow the installer to add Python to your system variable path during installation. Else you’ll have to do this manually later.&lt;/p&gt;

&lt;p&gt;To install Python on Windows OS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the installation file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the &lt;strong&gt;Add Python to Path&lt;/strong&gt; checkbox at the installation window’s bottom right. Then click &lt;strong&gt;Install Now&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The installation initializes and starts in the following menu.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2284%2F0%2AwwoxaOtT2rtfwK7R.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2284%2F0%2AwwoxaOtT2rtfwK7R.jpg" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While most Linux distributions may have Python pre-installed by default, you might still have to upgrade to a more recent version, as the system version might be obsolete to run Playwright. Playwright, however, works with Python version 3.7 or later.&lt;/p&gt;

&lt;p&gt;To install Python on Linux from scratch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  sudo apt-get install python 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2. Install Playwright and its WebKit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can install Playwright using &lt;strong&gt;pip&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   pip install playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re on Linux or Mac, you can use **pip3 **instead, which works with Python 3 on these platforms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either of the above commands run the Playwright installer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2616%2F0%2AOHEacD71zyXu5X55.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2616%2F0%2AOHEacD71zyXu5X55.jpg" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you’re using **conda **to manage dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   conda install playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on your choice of Python dependency installer, the above commands install the Playwright framework into your machine or Python virtual environment (if you use one).&lt;/p&gt;

&lt;p&gt;And to install the Playwright WebKit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  playwright install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command installs Playwright’s built-in WebKit. You’ll use this to bring up test scenarios for different web browsers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3. Create Project Folder.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step in this Playwright Python tutorial is to create a project folder for your automated testing. You can create one from the command line or your graphic user interface.&lt;/p&gt;

&lt;p&gt;We’ll use Visual Studio Code on the Windows platform in this Playwright Python tutorial. But you can use any IDE that works best for you.&lt;/p&gt;

&lt;p&gt;To create a folder on Windows and open it with VS Code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open any folder on your PC and right-click a blank space. Go to &lt;strong&gt;New &amp;gt; Folder&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Name your folder; this can be a descriptive name (for example &lt;strong&gt;playwright_test_folder&lt;/strong&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, open VS Code to your project folder. Open VS Code and click &lt;strong&gt;Open Folder&lt;/strong&gt;. Go to the folder you created earlier and select it to open VS Code to that directory.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3832%2F0%2AFNCJStPBS5A8XBpl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3832%2F0%2AFNCJStPBS5A8XBpl.jpg" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you’ve seen how to set up a development environment for testing your app in Python using Playwright — let’s dive into the coding aspect. But before that, remember we mentioned that Playwright has a code generator in this Playwright Python tutorial.&lt;/p&gt;

&lt;p&gt;You’ll see how this code generator works in the following section of this tutorial on Playwright Python since it shows you how to select elements on your website when writing tests.&lt;/p&gt;

&lt;p&gt;Run your Playwright test scripts instantly on 50+ browser and OS combinations. &lt;a href="https://accounts.lambdatest.com/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=register" rel="noopener noreferrer"&gt;Try LambdaTest Now!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: &lt;a href="https://www.lambdatest.com/jest?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Jest testing&lt;/a&gt; Tutorial: Complete Guide to Jest Testing&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the Playwright Code Generator work?
&lt;/h2&gt;

&lt;p&gt;As mentioned in the earlier section of this Playwright Python tutorial, the Playwright code generator makes it easy to scan the DOM without going to the inspection tab of your browser. Although it limits browser selection flexibility and is not as clean as writing custom tests, it’s also a nifty way for no-code lovers to auto-generate test scripts while interacting with the UI.&lt;/p&gt;

&lt;p&gt;The code generator works in two ways. You can use it to pick out your website’s selectors. Or you can generate an entire test case script with its record and play functionality.&lt;/p&gt;

&lt;p&gt;Open your terminal to your project root folder and use the following command to spin up a selector generator for your app. In my case, I’ll use the LambdaTest e-commerce playground, so remember to replace this with your website’s URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playWright codegen https://ecommerce-playground.lambdatest.io/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command generates the appropriate selectors as you hover on the elements on a web page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ap97V9cr_jY70yu2Z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ap97V9cr_jY70yu2Z.png" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look at the image above closely. You’ll see that the &lt;strong&gt;My account&lt;/strong&gt; dropdown on that page generates a selector. This helps determine how the Playwright locator finds elements or features during testing.&lt;/p&gt;

&lt;p&gt;To generate a test script into a Python file from your interaction with the target website, paste the following command in your terminal, replacing &lt;a href="https://ecommerce-playground.lambdatest.io/" rel="noopener noreferrer"&gt;https://ecommerce-playground.lambdatest.io/&lt;/a&gt; with your app’s URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright codegen — target python -o example2.py https://ecommerce-playground.lambdatest.io/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command brings up a browser like the first one. But this time, it tells Playwright to write test code into the target file &lt;strong&gt;(example2.py)&lt;/strong&gt; as you interact with the specified website. You don’t need to create the target file explicitly. The Playwright does this automatically.&lt;/p&gt;

&lt;p&gt;Now open your text editor to your project folder. You should see the generated Python script (&lt;strong&gt;example2.py&lt;/strong&gt; in my case).&lt;/p&gt;

&lt;p&gt;Here’s the website and the code generated from interacting with it below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOBzgBHk0_to655Et.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOBzgBHk0_to655Et.png" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you place the generated Python script and the website side-by-side, as shown above, you’ll see the code changing dynamically in the Python script as you interact with your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros of the Playwright Code Generator:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It auto-generates code, which can be a good starting point if you need to extend the use case further.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handy for picking test selectors in custom automated tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can generate code for any Playwright-supported programming language.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons of the Playwright Code Generator:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Generated code is not scalable and maintainable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s not suitable for testing complex websites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There’s no way to execute parallel tests since it only generates one code file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The generated code is hard to read and debug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It doesn’t provide room for connecting to a cloud grid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The codebase becomes messier as you generate more tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The test cases are repetitive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: &lt;a href="https://www.lambdatest.com/appium-mobile-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Appium&lt;/a&gt; Cloud For App Automation- Test your Native, Hybrid, and Web Apps on Appium mobile device cloud of 3000+ different real devices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Playwright Locators and Selectors
&lt;/h2&gt;

&lt;p&gt;As with most testing frameworks, locators and selectors are some of the core features of Playwright.&lt;/p&gt;

&lt;p&gt;Like &lt;a href="https://www.lambdatest.com/blog/locators-in-selenium-webdriver-with-examples/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium locators&lt;/a&gt;, you use Playwright selectors to specify the position of an element within the DOM. The locator is a class that points Playwright to the specified DOM elements so it can perform events on them.&lt;/p&gt;

&lt;p&gt;The locator holds off an event and triggers auto-wait, which keeps retrying the test but fails after 30 seconds if it can’t find an element. The locator and selector in Playwright work hand-in-hand.&lt;/p&gt;

&lt;p&gt;For example, the following locator performs a click event on the selected element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    page.locator(‘input[name=”Search”]’).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The selector in the above example is &lt;strong&gt;‘input[name=”search”]’&lt;/strong&gt;, while the &lt;strong&gt;page.locator()&lt;/strong&gt; function points to the selected element to perform JavaScript events on it (a &lt;strong&gt;click&lt;/strong&gt; event in this case). However, the &lt;strong&gt;page&lt;/strong&gt;, in this case, is a browser context instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3786%2F0%2AFhwIXinMW2yfdnNF.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3786%2F0%2AFhwIXinMW2yfdnNF.jpg" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: How To Debug Websites Using &lt;a href="https://www.lambdatest.com/blog/debug-websites-using-safari-developer-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Developer Tools for safari&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Python end to end testing with Playwright
&lt;/h2&gt;

&lt;p&gt;Before you start testing, you may want to inspect the website elements to pick the selectors for your test. Place your cursor on a &lt;strong&gt;web element &amp;gt; right-click&lt;/strong&gt; it and go to *&lt;em&gt;Inspect *&lt;/em&gt;(for Chrome or any other web browser of your choice).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; You can use the Playwright code generator to generate the selectors instead. Simply launch it using the playwright codegen Website_URL command. Hover over the elements and reuse the generated selectors in your test code.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, Codegen is extremely useful when it comes to generating selectors since selectors are an integral part of any automation test code.&lt;/p&gt;

&lt;p&gt;We would run the tests using Playwright Python in series and parallel. And our test scenario will consider a practical user story to demonstrate our end to end test. Read through this Playwright Python tutorial to learn more about &lt;a href="https://www.lambdatest.com/blog/what-is-parallel-testing-and-why-to-adopt-it/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;parallel testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ll run our test on the LambdaTest cloud grid. So you’ll need to grab your username and secret key from your &lt;a href="https://accounts.lambdatest.com/login?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=login" rel="noopener noreferrer"&gt;LambdaTest Build Dashboard&lt;/a&gt; by clicking the Access Key tab at the top-right:&lt;/p&gt;

&lt;p&gt;By using a &lt;a href="https://www.lambdatest.com/blog/benefits-of-cloud-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cloud testing&lt;/a&gt; platform like LambdaTest, you can dramatically cut down the time taken to run your Playwright Python tests by using a browser farm of 50+ browsers and browser versions of Chrome, Chromium, Microsoft Edge, Mozilla Firefox, and even Webkit.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ioJaNCYX7Qc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also subscribe to the &lt;a href="https://www.youtube.com/channel/UCCymWVaTozpEng_ep0mdUyw?sub_confirmation=1" rel="noopener noreferrer"&gt;LambdaTest YouTube Channel&lt;/a&gt; and stay updated with the latest tutorial around &lt;a href="https://www.lambdatest.com/automated-browser-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated browser testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/cypress-e2e-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Cypress E2E testing&lt;/a&gt;, &lt;a href="https://www.lambdatest.com/learning-hub/mobile-app-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Mobile App Testing&lt;/a&gt;, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: How To Debug Websites Using &lt;a href="https://www.lambdatest.com/blog/debug-websites-using-safari-developer-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;dev tools in  Safari&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2486%2F0%2Atq7CyuhLfn0aIb0c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2486%2F0%2Atq7CyuhLfn0aIb0c.jpg" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tests are demonstrated using the &lt;a href="https://www.lambdatest.com/selenium-playground/simple-form-demo?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;LambdaTest e-commerce playground.&lt;/a&gt; The use cases for this Playwright Python tutorial are below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Scenario — 1 (New User Registration)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The user launches the LambdaTest e-commerce playground registration page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fills out the registration form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User submits the registration form.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to their dashboard for the first time.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Test Scenario — 2 (Login and Purchase Item)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The user logs in another time with the registered account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Searches for a product.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user selects the product searched for in step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds the product to the cart.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The user checks out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perform logout.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Playwright Python Test Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will adopt the &lt;a href="https://www.lambdatest.com/blog/page-object-model-in-selenium-python/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Page Object Model (POM)&lt;/a&gt; design pattern to structure the test project. So our code structure, in this case, separates concerns into different files in separate folders for modularization. This helps us scale our code later on and get rid of complexities.&lt;/p&gt;

&lt;p&gt;Maintainability and scalability of the source code are some of the biggest plus points of the Page Object Model design pattern.&lt;/p&gt;

&lt;p&gt;For instance, you might want to separate parallel test cases from single ones along the line.&lt;/p&gt;

&lt;p&gt;Here’s the Playwright Python test structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Project Directory
            |-----------elementSelectors
            |                 |----------------loginAndBuySelectors.py
            |                 |----------------registrationPageSelectors.py
            |
            |------------testCapabilities
            |                 |-----------------testCaps.py
            |
            |-------------testScenarios
            |                 |-----------------.env
            |                 |-----------------parallelLoginBuyRun.py
            |                 |-----------------parallelSignupRun.py
            |                 |-----------------singleLoginBuyRun.py
            |                 |-----------------singleSignupRun.py
            |
            |---------------testScripts
                              |-----------------parallelLoginBuyScript
                              |-----------------parallelSignup.py
                              |-----------------singleLoginBuyScript.py
                              |-----------------singleSignupScript.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;elementSelectors&lt;/strong&gt; folder contains the selectors for all the test scenarios. All the capabilities required to run all the test suites are inside the &lt;strong&gt;testCapabilities&lt;/strong&gt; directory. This folder has only one file, which defines the capabilities shared by all test cases.&lt;/p&gt;

&lt;p&gt;We also place all test actions (event handlers) inside the **testScripts **folder. Each file in this folder holds the class handling event methods. And finally, the **testScenarios **directory contains the test runners for each test case. To run any test, you only need to run each file here.&lt;/p&gt;

&lt;p&gt;Therefore, we have to place the &lt;strong&gt;.env&lt;/strong&gt; file in this &lt;strong&gt;testScenarios *&lt;em&gt;folder since all imported modules will pick declared environment variables from it while running the test. Remember that the *&lt;/em&gt;.env&lt;/strong&gt; file holds all secret parameters, including your cloud grid key and username.&lt;/p&gt;

&lt;p&gt;Here’s the VS Code screenshot of the project directory used for this Playwright Python tutorial:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3816%2F0%2A4znIUyHMm6brpwgg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3816%2F0%2A4znIUyHMm6brpwgg.jpg" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we start by setting up the test capabilities for the entire test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Capabilities Implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;testCapabilities / testCaps.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   import json
    import os
    import urllib.parse
    import subprocess
    from dotenv import load_dotenv

    load_dotenv('.env')
    username = os.getenv("my_username")
    gridAcessKey = os.getenv("access_key")

    playwrightVersion = str(subprocess.getoutput('playwright --version')).strip().split(" ")[1]


    capabilities =[{
            'browserName': 'Chrome',  # Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
            'browserVersion': 'latest',
            'platform': 'Windows 10',
            'build': 'E2E for Chrome POM',
            'name': 'Playwright Test',
            'user': username,
            'accessKey': gridAcessKey,
            'console': True,
            'playwrightversion': playwrightVersion
        },
        {
            'browserName': 'MicrosoftEdge',  # Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
            'browserVersion': 'latest',
            'platform': 'Windows 10',
            'build': 'E2E for POM Egde',
            'name': 'Playwright Test Case 2',
            'user': username,
            'accessKey': gridAcessKey,
            'console': True,
            'playwrightversion': playwrightVersion
        }
        ]

    class testCapabilities:
        def __init__(self) -&amp;gt; None:
            self.lambdatestGridURL = 'wss://cdp.lambdatest.com/playwright?capabilities='

        def Chrome(self):
            self.stringifiedCaps = urllib.parse.quote(json.dumps(capabilities[0]))
            return self.lambdatestGridURL+self.stringifiedCaps
        def Edge(self):
            self.stringifiedCaps1 = urllib.parse.quote(json.dumps(capabilities[1]))
            return self.lambdatestGridURL+self.stringifiedCaps1

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: &lt;a href="https://www.lambdatest.com/blog/emulator-vs-simulator-vs-real-device/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Emulator vs Simulator&lt;/a&gt; vs Real Device Testing: Key Differences&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright Python Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;testCaps.py&lt;/strong&gt; file contains the capabilities module required to run all our test cases, including single and parallel tests. So you don’t have to change it for subsequent test cases while running the Playwright Python test — unless you want to add more capabilities to the array, which involves scaling the methods.&lt;/p&gt;

&lt;p&gt;You start by importing all the necessary packages to run this Playwright Python module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import json
        import os
        import urllib.parse
        import subprocess
        from dotenv import load_dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, load your cloud grid access key and username from the environmental variables using the &lt;strong&gt;dotenv&lt;/strong&gt; package, as you’ll provide them in the capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    load_dotenv('.env')
        username = os.getenv("my_username")
        gridAcessKey = os.getenv("access_key")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll also provide the Playwright version as a string inside the test capability. In this case, we extract this value using the subprocess module. Then we clean it with Python’s built-in **strip **and **split **functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwrightVersion = str(subprocess.getoutput(‘playwright — version’)).strip().split(“ “)[1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each capability is a dictionary specifying settings for the test. There are two capabilities in the array — in this case (Chrome and Microsoft Edge). Therefore we can call them individually in separate methods using an array index. And that makes it easy to scale to perform cross browser testing using Playwright Python — even in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    capabilities =[{
                'browserName': 'Chrome',  # Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
                'browserVersion': 'latest',
                'platform': 'Windows 10',
                'build': 'E2E for Chrome POM',
                'name': 'Playwright Test',
                'user': username,
                'accessKey': gridAcessKey,
                'console': True,
                'playwrightversion': playwrightVersion
            },
            {
                'browserName': 'MicrosoftEdge',  # Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
                'browserVersion': 'latest',
                'platform': 'Windows 10',
                'build': 'E2E for POM Egde',
                'name': 'Playwright Test Case 2',
                'user': username,
                'accessKey': gridAcessKey,
                'console': True,
                'playwrightversion': playwrightVersion
            }
            ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The **testCapabilities **class holds the Chrome and Microsoft Edge capability methods. First, you initialize this class with the cloud grid URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    class testCapabilities:
            def __init__(self) -&amp;amp;gt; None:
                self.lambdatestGridURL = 'wss://cdp.lambdatest.com/playwright?capabilities='

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LamdaTest grid URL for Playwright, as indicated above, is &lt;strong&gt;self.lambdatestGridURL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You then extract the capability for each browser method (&lt;strong&gt;Chrome&lt;/strong&gt; and &lt;strong&gt;Edge&lt;/strong&gt;) using its index position. Then concatenate each with the grid URL inherited from the &lt;strong&gt;&lt;strong&gt;init&lt;/strong&gt;&lt;/strong&gt; function.&lt;/p&gt;

&lt;p&gt;The **Chrome **method capability dictionary is at index zero (first item in the array):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    self.stringifiedCaps = urllib.parse.quote(json.dumps(capabilities[0]))
                return self.lambdatestGridURL+self.stringifiedCaps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Edge()&lt;/strong&gt; method gets the second dictionary in the array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    self.stringifiedCaps1 = urllib.parse.quote(json.dumps(capabilities[1]))
                return self.lambdatestGridURL+self.stringifiedCaps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hence, this design helps you run your test singly or in parallel based on the different capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation of the Registration Test Scenario:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;elementSelectors/registrationPageSelectors.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    webElements = {
        'webpage': "https://ecommerce-playground.lambdatest.io/index.php?route=account/register",
        'First_Name': 'input[placeholder="First Name"]',
        'Last_Name': 'input[placeholder="Last Name"]',
        'E-Mail': 'input[placeholder="E-Mail"]',
        'Telephone': 'input[placeholder="Telephone"]',
        'Password': 'input[placeholder="Password"]',
        'Confirm_Password': 'input[placeholder="Password Confirm"]',
        'Subscribe': 'label:has-text("No")',
        'Privacy_Policy': 'label:has-text("I have read and agree to the Privacy Policy")',
        'Submit': 'input[value="Continue"]',
        'Continue': "text=Continue"
    }


    class elementSelector:
        def __init__(self) -&amp;gt; None:
            self.webpage = webElements["webpage"]
            self.firstname = webElements["First_Name"]
            self.lastname = webElements["Last_Name"]
            self.email = webElements["E-Mail"]
            self.telephone = webElements["Telephone"]
            self.password = webElements["Password"]
            self.confirmpassword = webElements["Confirm_Password"]
            self.subscribe = webElements["Subscribe"]
            self.privacypolicy = webElements["Privacy_Policy"]
            self.submit = webElements["Submit"]
            self.todashboard = webElements["Continue"]

        def webPage(self):
            return self.webpage
        def firstName(self):
            return self.firstname
        def lastName(self):
            return self.lastname
        def eMail(self):
            return self.email
        def Telephone(self):
            return self.telephone
        def Password(self):
            return self.password
        def confirmPassword(self):
            return self.confirmpassword
        def Subscribe(self):
            return self.subscribe  
        def privacyPolicy(self):
            return self.privacypolicy
        def Submit(self):
            return self.submit
        def goToDashboard(self):
            return self.todashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;testScripts / singleSignupScript.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from playwright.sync_api import sync_playwright
    import sys
    sys.path.append(sys.path[0] + "/..")


    from elementSelectors.registrationPageSelectors import elementSelector
    from testCapabilities.testCaps import testCapabilities

    select = elementSelector()

    capability = testCapabilities()

    def set_test_status(page, status, remark):
            page.evaluate("_ =&amp;gt; {}",
            "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")


    class Register:
        def __init__(self, playwright) -&amp;gt; None:
            self.browser = playwright.chromium.connect(capability.Chrome())
            page = self.browser.new_page()
            self.page = page
        def launchWeb(self):
            self.page.goto(select.webPage())
            title = self.page.title()
            print(title)

        def fillFirstName(self, data):
            self.page.locator(select.firstName()).fill(data)

        def fillLastName(self, data):
            self.page.locator(select.lastName()).fill(data)

        def fillEmail(self, data):
            self.page.locator(select.eMail()).fill(data)

        def fillPhone(self, data):
            self.page.locator(select.Telephone()).fill(data)

        def fillPassword(self, data):
            self.page.locator(select.Password()).fill(data)

        def confirmPassword(self, data):
            self.page.locator(select.confirmPassword()).fill(data)

        def subscribe(self):
            self.page.locator(select.Subscribe()).click()

        def acceptPolicy(self):
            self.page.locator(select.privacyPolicy()).click()

        def submit(self):
            self.page.locator(select.Submit()).click()

        def continueToDashboard(self):
            self.page.locator(select.goToDashboard()).click()

        def getSuccessStatus(self):
            return set_test_status(self.page, "passed", "Success")

        def getFailedStatus(self):
            return set_test_status(self.page, "failed", "Test failed")

        def closeBrowser(self):
            self.browser.close()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;testScenario / singleSignupRun.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
    sys.path.append(sys.path[0] + "/..")

    from testScripts.singleSignupScript import Register
    from playwright.sync_api import sync_playwright


    with sync_playwright() as playwright:

        try:
            playwright = Register(playwright)
            playwright.launchWeb()
            playwright.fillFirstName("Idowu")
            playwright.fillLastName("Omisola")
            playwright.fillEmail("anEmailgmai@gmail.com")
            playwright.fillPhone("08122334433")
            playwright.fillPassword("mypassword")
            playwright.confirmPassword("mypassword")
            playwright.subscribe()
            playwright.acceptPolicy()
            playwright.submit()
            playwright.continueToDashboard()
            playwright.getSuccessStatus()
        except:
            playwright.getFailedStatus()

        playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Playwright Python Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — elementSelectors / registrationPageSelectors.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We insert all the web element selectors, including the test site URL, into a dictionary inside the &lt;strong&gt;registrationPageSelectors.py&lt;/strong&gt; file:&lt;/p&gt;

&lt;p&gt;For instance, the Email field selector takes this format in the dictionary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ‘E-Mail’: ‘input[placeholder=”E-Mail Address”]’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entire element selector dictionary looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    webElements = {
            'webpage': "https://ecommerce-playground.lambdatest.io/index.php?route=account/register",
            'First_Name': 'input[placeholder="First Name"]',
            'Last_Name': 'input[placeholder="Last Name"]',
            'E-Mail': 'input[placeholder="E-Mail"]',
            'Telephone': 'input[placeholder="Telephone"]',
            'Password': 'input[placeholder="Password"]',
            'Confirm_Password': 'input[placeholder="Password Confirm"]',
            'Subscribe': 'label:has-text("No")',
            'Privacy_Policy': 'label:has-text("I have read and agree to the Privacy Policy")',
            'Submit': 'input[value="Continue"]',
            'Continue': "text=Continue"
        }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is to turn these into the attributes that initiate the &lt;strong&gt;elementSelector&lt;/strong&gt; class by calling each element by its key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    class elementSelector:
            def __init__(self) -&amp;amp;gt; None:
                self.webpage = webElements["webpage"]
                self.firstname = webElements["First_Name"]
                self.lastname = webElements["Last_Name"]
                self.email = webElements["E-Mail"]
                self.telephone = webElements["Telephone"]
                self.password = webElements["Password"]
                self.confirmpassword = webElements["Confirm_Password"]
                self.subscribe = webElements["Subscribe"]
                self.privacypolicy = webElements["Privacy_Policy"]
                self.submit = webElements["Submit"]
                self.todashboard = webElements["Continue"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we declare them as methods of the &lt;strong&gt;elementSelector&lt;/strong&gt; class like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def webPage(self):
                return self.webpage
            def firstName(self):
                return self.firstname
            def lastName(self):
                return self.lastname
            def eMail(self):
                return self.email
            def Telephone(self):
                return self.telephone
            def Password(self):
                return self.password
            def confirmPassword(self):
                return self.confirmpassword
            def Subscribe(self):
                return self.subscribe  
            def privacyPolicy(self):
                return self.privacypolicy
            def Submit(self):
                return self.submit
            def goToDashboard(self):
                return self.todashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FileName — testScripts / singleSignupScript.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;singleSignupScript.py&lt;/strong&gt; file contains the test event methods. We start by importing the built-in modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   from playwright.sync_api import sync_playwright
        import sys

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The **sys **package connects the Python files in different folders and makes imported custom modules visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   sys.path.append(sys.path[0] + “/..”)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The directory path (“/..”) is a file-level declaration, showing that the imported module is two steps away from the root folder. So it might change in your case, depending on your project structure.&lt;/p&gt;

&lt;p&gt;After this, we import and instantiate the &lt;strong&gt;elementSelector&lt;/strong&gt; and &lt;strong&gt;testCapability&lt;/strong&gt; classes from their respective modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from elementSelectors.registrationPageSelectors import elementSelector
        from testCapabilities.testCaps import testCapabilities

        select = elementSelector()

        capability = testCapabilities()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, for instance, to call the Chrome method from the &lt;strong&gt;testCapability&lt;/strong&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    capability.Chrome()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to get a method, say the &lt;strong&gt;webPage&lt;/strong&gt; from the &lt;strong&gt;elementSelector&lt;/strong&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    select.webPage()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start the **Register **class, it inherits the Playwright package methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def __init__(self, playwright) -&amp;amp;gt; None:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, to initiate the &lt;strong&gt;Register **class, we connected to the Chrome method (which defines the grid URL and the JSONified capabilities). The **self.page&lt;/strong&gt; attribute is an instance of the browser context containing the locator actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    self.browser = playwright.chromium.connect(capability.Chrome())
                page = self.browser.new_page()
                self.page = page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;launchWeb **method opens the website using the page instance **goto **method by calling the website URL with the **select.webPage()&lt;/strong&gt; instance of the **elementSelector **class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def launchWeb(self):
                self.page.goto(select.webPage())
                title = self.page.title()
                print(title)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of the other attributes in the class gets the appropriate method similarly. For readability, each field element accepts a **data **keyword.&lt;/p&gt;

&lt;p&gt;For example, to fill in the first name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def fillFirstName(self, data):
                self.page.locator(select.firstName()).fill(data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The elements that accept a click event doesn’t take any data. To click the Subscribe button, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def subscribe(self):
                self.page.locator(select.Subscribe()).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;set_test_status **function at the top of the script returns test status on the LambdaTest Grid UI. So once a test passes, it returns **passed&lt;/strong&gt;, but you get a **failed **message for failed tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def set_test_status(page, status, remark):
                page.evaluate("_ =&amp;amp;gt; {}",
                "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")

This later becomes a part of the **Register** class methods:

    def getSuccessStatus(self):
                return set_test_status(self.page, "passed", "Success")

            def getFailedStatus(self):
                return set_test_status(self.page, "failed", "Test failed")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FileName — testScenario / singleSignupRun.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;singleSignupRun.py&lt;/strong&gt; file also starts with module imports. But notably, we imported the &lt;strong&gt;Register **class from the **singleSignupScript **module. We then created an event loop using the sync class of Playwright and passed this as **playwright&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    with sync_playwright() as playwright:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that the **Register **class inherited the Playwright method earlier. To actualize this, we pass the **playwright **variable as an instance of the **Register **class. And it also now bears the inherited Playwright sync class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright = Register(playwright)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore, the event loop executes the registration test steps in this order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Launch the test website using the launch method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.launchWeb()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Fill out the registration form. So for form fields, you must call and fill them since they accept a positional &lt;strong&gt;data&lt;/strong&gt; argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.fillFirstName("Idowu")
                playwright.fillLastName("Omisola")
                playwright.fillEmail("anEmailgmai@gmail.com")
                playwright.fillPhone("08122334433")
                playwright.fillPassword("mypassword")
                playwright.confirmPassword("mypassword")
                playwright.subscribe()
                playwright.acceptPolicy()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Submit the registration form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    playwright.submit()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: Visit your dashboard for the first time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   playwright.continueToDashboard()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;getSuccessStatus()&lt;/strong&gt; method returns a &lt;strong&gt;passed&lt;/strong&gt; message on the grid if the code in the try block executes successfully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; playwright.getSuccessStatus()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, it runs the &lt;strong&gt;getfailedStatus()&lt;/strong&gt; method and returns a **failed **message on the grid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    except Exception as err:
                playwright.getFailedStatus()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we close the browser outside the &lt;strong&gt;try-except&lt;/strong&gt; block to prevent an endless loop, which throws an error during execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Playwright Python Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the test runner file (&lt;strong&gt;singleSignupRun.py&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; python singleSignupRun.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test executes successfully on the LambdaTest grid as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3808%2F0%2Ar_RAOl1_hltkOGxF.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3808%2F0%2Ar_RAOl1_hltkOGxF.jpg" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: Cross &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Browser Test&lt;/a&gt; Cloud- Browser &amp;amp; app testing cloud to perform both exploratory and automated testing across 3000+ different browsers, real devices and operating systems.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Login and Product Purchase Test Case Implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The element selectors for the login test case are inside the &lt;strong&gt;loginAndBuySelectors.py&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;elementSelectors/loginAndBuySelectors.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   webElements = {
        'webpage': "https://ecommerce-playground.lambdatest.io/index.php?route=account/login",
        'E-Mail': 'input[placeholder="E-Mail Address"]',
        'Password': 'input[placeholder="Password"]',
        'Login': 'input:has-text("Login")',
        'Search': 'input[name="search"] &amp;gt;&amp;gt; nth = 0',
        'searchbutton': 'div[class="search-button"]:has-text("Search")',
        'product': 'h4[class="title"]:has-text("Nikon D300") &amp;gt;&amp;gt; nth = 0',
        'addcart': 'div[id="entry_216842"]:has-text("Add to Cart")',
        'checkoutmodal': 'div[role="alert"]:has-text("Checkout")',
        'Hoverable': 'a[role="button"]:has-text("My account")',
        'Logout': 'span:has-text("Logout")'
    }

    class elementSelector:
        def __init__(self) -&amp;gt; None:
            self.webpage = webElements['webpage']
            self.email = webElements['E-Mail']
            self.password = webElements['Password']
            self.login = webElements['Login']
            self.hover = webElements['Hoverable']
            self.searchproduct = webElements['Search']
            self.product = webElements['product']
            self.addcart = webElements['addcart']
            self.checkout = webElements['checkoutmodal']
            self.searchbutton = webElements['searchbutton']
            self.logout = webElements['Logout']
        def webPage(self):
            return self.webpage
        def eMail(self):
            return self.email
        def Password(self):
            return self.password
        def loginAccount(self):
            return self.login
        def hoverBox(self):
            return self.hover
        def searchProduct(self):
            return self.searchproduct
        def Product(self):
            return self.product
        def addCart(self):
            return self.addcart
        def checkOut(self):
            return self.checkout
        def searchButton(self):
            return self.searchbutton
        def logoutUser(self):
            return self.logout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;testScripts / singleLoginButScript.py&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   from playwright.sync_api import sync_playwright
    import sys
    sys.path.append(sys.path[0] + "/..")


    from elementSelectors.loginAndBuySelectors import elementSelector
    from testCapabilities.testCaps import testCapabilities

    select = elementSelector()

    capability = testCapabilities()

    # Setting grid status to failed or passed
    def set_test_status(page, status, remark):
            page.evaluate("_ =&amp;gt; {}",
            "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")

    class LoginAndBuy:

        def __init__(self, playwright) -&amp;gt; None:
            self.browser = playwright.chromium.connect(capability.Chrome())
            page = self.browser.new_page()
            self.page = page

        def launchWeb(self):
            self.page.goto(select.webPage())
            title = self.page.title()
            print(title)

        def fillEmail(self, data):
            self.page.locator(select.eMail()).fill(data)

        def fillPassword(self, data):
            self.page.locator(select.Password()).fill(data)

        def clickLogin(self):
            self.page.locator(select.loginAccount()).click()

        def fillSearchBox(self, data):
            self.page.locator(select.searchProduct()).fill(data)

        def clickSearchButton(self):
            self.page.locator(select.searchButton()).click()

        def clickProduct(self):
            self.page.locator(select.Product()).click()

        def clickAddToCart(self):
            self.page.locator(select.addCart()).click()

        def clickCheckOutModal(self):
            self.page.locator(select.checkOut()).click()

        def hoverMenuBox(self):
            self.page.locator(select.hoverBox()).hover()

        def clickLogout(self):
            self.page.locator(select.logoutUser()).click()

        def getSuccessStatus(self):
            set_test_status(self.page, "passed", "Success")

        def getFailedStatus(self):
            set_test_status(self.page, "failed", "Test failed")

        def closeBrowser(self):
            self.browser.close()


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;FileName *&lt;/em&gt;—&lt;em&gt;testScenarios / singleLoginBuyRun.py:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
    sys.path.append(sys.path[0] + "/..")

    from testScripts.singleLoginBuyScript import LoginAndBuy
    from playwright.sync_api import sync_playwright


    with sync_playwright() as playwright:
        try:
            playwright = LoginAndBuy(playwright)
            playwright.launchWeb()
            playwright.fillEmail("anEmailgmai@gmail.com")
            playwright.fillPassword("mypassword")
            playwright.clickLogin()
            playwright.fillSearchBox("Nikon")
            playwright.clickSearchButton()
            playwright.clickProduct()
            playwright.clickAddToCart()
            playwright.clickCheckOutModal()

            playwright.hoverMenuBox()
            playwright.clickLogout()
            playwright.getSuccessStatus()
        except:
            playwright.getFailedStatus()
        playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Playwright Python Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — elementSelectors / loginAndBuySelectors.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As with the registration test case, we place all the login page element selectors and the website URL in a dictionary (&lt;strong&gt;webElements&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   webElements = {
            'webpage': "https://ecommerce-playground.lambdatest.io/index.php?route=account/login",
            'E-Mail': 'input[placeholder="E-Mail Address"]',
            'Password': 'input[placeholder="Password"]',
            'Login': 'input:has-text("Login")',
            'Search': 'input[name="search"] &amp;amp;gt;&amp;amp;gt; nth = 0',
            'searchbutton': 'div[class="search-button"]:has-text("Search")',
            'product': 'h4[class="title"]:has-text("Nikon D300") &amp;amp;gt;&amp;amp;gt; nth = 0',
            'addcart': 'div[id="entry_216842"]:has-text("Add to Cart")',
            'checkoutmodal': 'div[role="alert"]:has-text("Checkout")',
            'Hoverable': 'a[role="button"]:has-text("My account")',
            'Logout': 'span:has-text("Logout")'
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;Search *&lt;em&gt;and **product **elements have the *&lt;/em&gt;&amp;gt;&amp;gt; nth = index&lt;/strong&gt; because each of these DOM elements has an nth node with similar selectors. So the **nth **argument helps specify the index position of the children, starting from zero.&lt;/p&gt;

&lt;p&gt;For example, to select the first product from a group of similar ones as we did above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ‘product’: ‘h4[class=”title”]:has-text(“Nikon D300”) &amp;amp;gt;&amp;amp;gt; nth = 0’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use these elements to initiate the **elementSelector **class by attaching each to an attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   class elementSelector:
            def __init__(self) -&amp;amp;gt; None:
                self.webpage = webElements['webpage']
                self.email = webElements['E-Mail']
                self.password = webElements['Password']
                self.login = webElements['Login']
                self.hover = webElements['Hoverable']
                self.searchproduct = webElements['Search']
                self.product = webElements['product']
                self.addcart = webElements['addcart']
                self.checkout = webElements['checkoutmodal']
                self.searchbutton = webElements['searchbutton']
                self.logout = webElements['Logout']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we create a method that returns each attribute. These methods will handle Playwright locator events in the test script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def webPage(self):
                return self.webpage
            def firstName(self):
                return self.firstname
            def lastName(self):
                return self.lastname
            def eMail(self):
                return self.email
            def Telephone(self):
                return self.telephone
            def Password(self):
                return self.password
            def confirmPassword(self):
                return self.confirmpassword
            def Subscribe(self):
                return self.subscribe  
            def privacyPolicy(self):
                return self.privacypolicy
            def Submit(self):
                return self.submit
            def goToDashboard(self):
                return self.todashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, the above block attaches each attribute to the **elementSelector **class method. We can use these easily in another file; you only have to call each from an instance of the **elementSelector **class. That’s one of the strong points of the Page Object Model (POM).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — testScripts / singleLoginBuyScript.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We start the &lt;strong&gt;singleLoginButScript.py&lt;/strong&gt; file by importing the synchronous Playwright and &lt;strong&gt;sys&lt;/strong&gt; packages. Then we use the sys append method to point Python to the system path before importing our custom modules (&lt;strong&gt;elementSelector and testCapabilities&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from playwright.sync_api import sync_playwright
        import sys
        sys.path.append(sys.path[0] + "/..")

        from elementSelectors.loginAndBuySelectors import elementSelector
        from testCapabilities.testCaps import testCapabilities

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create an instance of the &lt;strong&gt;elementSelector&lt;/strong&gt; and &lt;strong&gt;testCapabilities&lt;/strong&gt; classes to prevent conflict with the class inheritance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   select = elementSelector()

        capability = testCapabilities()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s now easy to call each method from these classes via their object instance. We leverage this to declare our methods in the &lt;strong&gt;LoginAndBuy&lt;/strong&gt; class, starting with initialization with the Chrome browser context. However, the initialization inherits the Playwright class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   class LoginAndBuy:

            def __init__(self, playwright) -&amp;amp;gt; None:
                self.browser = playwright.chromium.connect(capability.Chrome())
                page = self.browser.new_page()
                self.page = page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above snippet, &lt;strong&gt;capability.Chrome()&lt;/strong&gt; picks the &lt;strong&gt;Chrome()&lt;/strong&gt; method from the testCapabilities class. You can change this to Microsoft Edge by replacing &lt;strong&gt;Chrome()&lt;/strong&gt; with the &lt;strong&gt;Edge()&lt;/strong&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   self.browser = playwright.chromium.connect(capability.Edge())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other methods belong to the &lt;strong&gt;elementSelector **class. So the test case starts by launching the browser using the inherited browser context. Note how it selects the **webPage()&lt;/strong&gt; method from this class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def launchWeb(self):
                self.page.goto(select.webPage())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following three methods define the login process. Each form field accepts a &lt;strong&gt;data&lt;/strong&gt; keyword (the Email and password registered earlier):&lt;/p&gt;

&lt;p&gt;Below are the login steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    def fillEmail(self, data):
                self.page.locator(select.eMail()).fill(data)

            def fillPassword(self, data):
                self.page.locator(select.Password()).fill(data)

            def clickLogin(self):
                self.page.locator(select.loginAccount()).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, we search for a product, select it when found, then add it to the cart and checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  def fillSearchBox(self, data):
                self.page.locator(select.searchProduct()).fill(data)

            def clickSearchButton(self):
                self.page.locator(select.searchButton()).click()

            def clickProduct(self):
                self.page.locator(select.Product()).click()

            def clickAddToCart(self):
                self.page.locator(select.addCart()).click()

            def clickCheckOutModal(self):
                self.page.locator(select.checkOut()).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final test step is to log out of the website. The &lt;strong&gt;hover()&lt;/strong&gt; event makes the logout button accessible since it’s in a hoverable dropdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  def hoverMenuBox(self):
                self.page.locator(select.hoverBox()).hover()

            def clickLogout(self):
                self.page.locator(select.logoutUser()).click()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The **set_test_status **function at the top of the script helps communicate the test status to the cloud grid’s UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def set_test_status(page, status, remark):
                page.evaluate("_ =&amp;amp;gt; {}",
                "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes part of the **LoginAndBuy **class methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def getSuccessStatus(self):
                set_test_status(self.page, "passed", "Success")

            def getFailedStatus(self):
                set_test_status(self.page, "failed", "Test failed")

Finally, we close the browser context:

    def closeBrowser(self):
                self.browser.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FileName — testScenarios / singleLoginBuyRun.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;singleLoginBuyRun.py&lt;/strong&gt; file runs the login and product purchase test case. First, we import the Playwright sync module and resolve the system path using the sys package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
        sys.path.append(sys.path[0] + "/..")

        from playwright.sync_api import sync_playwright

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also have to import the **LoginAndBuy **class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from testScripts.singleLoginBuyScript import LoginAndBuy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is the class instance declaration inside the Playwright event loop, followed by website launch on the selected browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  with sync_playwright() as playwright:
            try:
                playwright = LoginAndBuy(playwright)
                playwright.launchWeb()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following steps occur within the event loop:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Log in another time with the registered account. Below are the login steps declaration within the event loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       playwright.fillEmail("anEmailgmai@gmail.com")
                playwright.fillPassword("mypassword")
                playwright.clickLogin()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Search for a product and go to the product page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.fillSearchBox("Nikon")
                playwright.clickSearchButton()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Select the item you searched to go to the product page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   playwright.clickProduct()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Add the selected product to the cart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.clickAddToCart()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;: Check out with the purchased product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; playwright.clickCheckOutModal()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt;: The event loop ends with the logout steps. The success status must be within the &lt;strong&gt;try&lt;/strong&gt; clause since it runs only if the series of code in the &lt;strong&gt;try&lt;/strong&gt; block work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.hoverMenuBox()
                playwright.clickLogout()
                playwright.getSuccessStatus()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, the failed status only runs if there’s an exception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   except:

       playwright.getFailedStatus()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we close the browser regardless of what happens in the event loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Execution of the Login and Product Purchase Test on the Cloud Grid:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To execute this test case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  python singleLoginBuyRun.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test runs successfully on the cloud grid as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ABLwmcbF0TQsRLMxK.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2ABLwmcbF0TQsRLMxK.jpg" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: Test on &lt;a href="https://www.lambdatest.com/test-on-safari-browsers?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Safari Browser Online&lt;/a&gt; with Real Mac Machines. Test on Latest Safari Desktop and Mobile Browsers for Cross Browser Compatibility.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing parallel testing with Playwright Python
&lt;/h2&gt;

&lt;p&gt;Performing cross-browser &lt;a href="https://www.lambdatest.com/blog/regression-testing-what-is-and-how-to-do-it/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;regression testing&lt;/a&gt; for multiple browsers at once helps find issues faster, allowing you to move on to other work. We will continue to maintain the same browser configurations for the parallel test for testing efficiency purposes.&lt;/p&gt;

&lt;p&gt;Running the test cases in parallel on the cloud grid helps you simulate an instance of servers in the cloud where you can run your test cases concurrently on separate cloud host machines. This helps check if your app works as it should in different integration environments.&lt;/p&gt;

&lt;p&gt;In this case, the parallel test concept is to iterate the test cases through a capabilities array. So for this section of this Playwright Python tutorial, we’ll run the registration and login tests on two browsing capabilities; Chrome and Microsoft Edge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The entire test suite shares the &lt;strong&gt;testCap.py&lt;/strong&gt; file, which we’ve shown earlier. However, the selector modules (&lt;strong&gt;registrationPageSelectors.py&lt;/strong&gt; and &lt;strong&gt;loginAndBuySelectors.py&lt;/strong&gt;) also remain the same for the signup and login to purchase parallel test cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Registration Parallel Test Implementation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**&lt;em&gt;FileName *&lt;/em&gt;— testScripts/parallelSignup.py*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   from playwright.sync_api import sync_playwright
    import sys
    sys.path.append(sys.path[0] + "/..")


    from elementSelectors.registrationPageSelectors import elementSelector
    from testCapabilities.testCaps import testCapabilities

    select = elementSelector()

    capability = testCapabilities()

    def set_test_status(page, status, remark):
            page.evaluate("_ =&amp;gt; {}",
            "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")

    class Register:
        def __init__(self, playwright) -&amp;gt; None:
            self.allCaps = [capability.Edge(), capability.Chrome()]
            self.browsers = [playwright.chromium.connect(i) for i in self.allCaps]
            pages = [i.new_page() for i in self.browsers]
            self.pages = pages
        def launchWeb(self):
            for page in self.pages:
                page.goto(select.webPage())
                title = page.title()
                print(title)
        def fillFirstName(self, data):
            for page in self.pages:
                page.locator(select.firstName()).fill(data)
        def fillLastName(self, data):
            for page in self.pages:
                page.locator(select.lastName()).fill(data)
        def fillEmail(self, data):
            for page in self.pages:
                page.locator(select.eMail()).fill(data)
        def fillPhone(self, data):
            for page in self.pages:
                page.locator(select.Telephone()).fill(data)
        def fillPassword(self, data):
            for page in self.pages:
                page.locator(select.Password()).fill(data)
        def confirmPassword(self, data):
            for page in self.pages:
                page.locator(select.confirmPassword()).fill(data)
        def subscribe(self):
            for page in self.pages:
                page.locator(select.Subscribe()).click()
        def acceptPolicy(self):
            for page in self.pages:
                page.locator(select.privacyPolicy()).click()
        def submit(self):
            for page in self.pages:
                page.locator(select.Submit()).click()
        def continueToDashboard(self):
            for page in self.pages:
                page.locator(select.goToDashboard()).click()
        def getSuccessStatus(self):
            for page in self.pages:
                set_test_status(page, "passed", "Success")

        def getFailedStatus(self):
            for page in self.pages:
                set_test_status(page, "failed", "Test failed")

        def closeBrowser(self):
            for browser in self.browsers:
                browser.close()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;em&gt;FileName *&lt;/em&gt;— testScenarios/parallelSignupRun.py*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
    sys.path.append(sys.path[0] + "/..")

    from testScripts.parallelSignup import Register
    from playwright.sync_api import sync_playwright


    with sync_playwright() as playwright:

        try:
            playwright = Register(playwright)
            playwright.launchWeb()
            playwright.fillFirstName("Idowu")
            playwright.fillLastName("Omisola")
            playwright.fillEmail("some7gmail@gmail.com")
            playwright.fillPhone("08122334433")
            playwright.fillPassword("mypassword")
            playwright.confirmPassword("mypassword")
            playwright.subscribe()
            playwright.acceptPolicy()
            playwright.submit()
            playwright.continueToDashboard()
            playwright.getSuccessStatus()
        except Exception as err:
            playwright.getFailedStatus()

        playwright.closeBrowser() 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Playwright Python Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — testScripts/parallelSignup.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We import the needed modules for the test at the top of the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from playwright.sync_api import sync_playwright
        import sys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;sys&lt;/strong&gt; module points Python to the root directory path. Then we import the &lt;strong&gt;elementSelector&lt;/strong&gt; and &lt;strong&gt;testCapabilities&lt;/strong&gt; classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from elementSelectors.registrationPageSelectors import elementSelector
        from testCapabilities.testCaps import testCapabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is the object instance creation. The &lt;strong&gt;select&lt;/strong&gt; variable is the elementSelector class instance, while &lt;strong&gt;capability&lt;/strong&gt; holds the &lt;strong&gt;testCapabilities&lt;/strong&gt; class instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    select = elementSelector()

        capability = testCapabilities()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We initiate the &lt;strong&gt;Register&lt;/strong&gt; class as we did in the previous single tests. But this time, we insert the &lt;strong&gt;capability&lt;/strong&gt; methods (&lt;strong&gt;Chrome()&lt;/strong&gt; and &lt;strong&gt;Edge()&lt;/strong&gt;) into a list — so we can iterate through each browser instance to spin up a cross-browser parallel test.&lt;/p&gt;

&lt;p&gt;So notably within the &lt;strong&gt;&lt;strong&gt;init&lt;/strong&gt;&lt;/strong&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    self.allCaps = [capability.Edge(), capability.Chrome()]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is an iteration of the browser contexts, ending with the self.pages inheriting the pages list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    self.browsers = [playwright.chromium.connect(i) for i in self.allCaps]
                pages = [i.new_page() for i in self.browsers]
                self.pages = pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;launchWeb()&lt;/strong&gt; method also iterates through the browser contexts to launch the test website in each browser. We then print out the title for each page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    def launchWeb(self):
                for page in self.pages:
                    page.goto(select.webPage())
                    title = page.title()
                    print(title)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This iteration continues for every test method under the **Register **class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  def fillFirstName(self, data):
                for page in self.pages:
                    page.locator(select.firstName()).fill(data)
            def fillLastName(self, data):
                for page in self.pages:
                    page.locator(select.lastName()).fill(data)
            def fillEmail(self, data):
                for page in self.pages:
                    page.locator(select.eMail()).fill(data)
            def fillPhone(self, data):
                for page in self.pages:
                    page.locator(select.Telephone()).fill(data)
            def fillPassword(self, data):
                for page in self.pages:
                    page.locator(select.Password()).fill(data)
            def confirmPassword(self, data):
                for page in self.pages:
                    page.locator(select.confirmPassword()).fill(data)
            def subscribe(self):
                for page in self.pages:
                    page.locator(select.Subscribe()).click()
            def acceptPolicy(self):
                for page in self.pages:
                    page.locator(select.privacyPolicy()).click()
            def submit(self):
                for page in self.pages:
                    page.locator(select.Submit()).click()
            def continueToDashboard(self):
                for page in self.pages:
                    page.locator(select.goToDashboard()).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then defined the status methods to get the appropriate messages in the grid UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def getSuccessStatus(self):
                for page in self.pages:
                    set_test_status(page, "passed", "Success")

            def getFailedStatus(self):
                for page in self.pages:
                    set_test_status(page, "failed", "Test failed")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script ends by closing the browser context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def closeBrowser(self):
                for browser in self.browsers:
                    browser.close()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FileName — testScenarios / parallelSignupRun.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing much has changed about the test runner file here. We import all the modules and point Python to the root directory, as we did earlier. However, this time, we import the &lt;strong&gt;Register&lt;/strong&gt; class from the &lt;strong&gt;parallelSignup&lt;/strong&gt; module since this is a parallel test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
        sys.path.append(sys.path[0] + "/..")

        from testScripts.parallelSignup import Register
        from playwright.sync_api import sync_playwright

from playwright.sync_api import sync_playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The methods called under &lt;strong&gt;sync_playwright()&lt;/strong&gt; event loop run the parallel signup test using the &lt;strong&gt;Register&lt;/strong&gt; class instance (playwright):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    with sync_playwright() as playwright:

            try:
                playwright = Register(playwright)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test steps haven’t changed. But this time, they run in parallel:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to the registration page on both browser contexts in consideration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    playwright.launchWeb()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Filling of the registration form occurs in parallel on both browsers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  playwright.fillFirstName("Idowu")
                playwright.fillLastName("Omisola")
                playwright.fillEmail("some7gmail@gmail.com")
                playwright.fillPhone("08122334433")
                playwright.fillPassword("mypassword")
                playwright.confirmPassword("mypassword")
                playwright.subscribe()
                playwright.acceptPolicy()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Submit the form on both browsers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.submit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: Go to your dashboard for the first time. Then end the test execution with a status message on the grid UI (passed or failed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.continueToDashboard()
                playwright.getSuccessStatus()
            except Exception as err:
                playwright.getFailedStatus()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, call the &lt;strong&gt;closeBrowser()&lt;/strong&gt; method to close all browser instances and end the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Registration Parallel Test Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the parallelSignupRun.py file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   python parallelSignupRun.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our parallel cross-browser test cases run simultaneously on the LambdaTest cloud grid as shown:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3812%2F0%2AG2mE57Un1tmzqc_e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3812%2F0%2AG2mE57Un1tmzqc_e.jpg" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation (Login and Purchase use case):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;**&lt;em&gt;FileName *&lt;/em&gt;— testScripts / parallelLoginBuyScript.py*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    from playwright.sync_api import sync_playwright
    import sys
    sys.path.append(sys.path[0] + "/..")


    from elementSelectors.loginAndBuySelectors import elementSelector
    from testCapabilities.testCaps import testCapabilities

    select = elementSelector()

    capability = testCapabilities()

    # Setting grid status to failed or passed
    def set_test_status(page, status, remark):
            page.evaluate("_ =&amp;gt; {}",
            "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")

    class LoginAndBuy:


        def __init__(self, playwright) -&amp;gt; None:
            self.allCaps = [capability.Edge(), capability.Chrome()]
            self.browsers = [playwright.chromium.connect(i) for i in self.allCaps]
            pages = [i.new_page() for i in self.browsers]
            self.pages = pages

        def launchWeb(self):
            for page in self.pages:
                page.goto(select.webPage())
                title = page.title()
                print(title)

        def fillEmail(self, data):
            for page in self.pages:
                page.locator(select.eMail()).fill(data)

        def fillPassword(self, data):
            for page in self.pages:
                page.locator(select.Password()).fill(data)

        def clickLogin(self):
            for page in self.pages:
                page.locator(select.loginAccount()).click()

        def fillSearchBox(self, data):
            for page in self.pages:
                page.locator(select.searchProduct()).fill(data)

        def clickSearchButton(self):
            for page in self.pages:
                page.locator(select.searchButton()).click()

        def clickProduct(self):
            for page in self.pages:
                page.locator(select.Product()).click()

        def clickAddToCart(self):
            for page in self.pages:
                page.locator(select.addCart()).click()

        def clickCheckOutModal(self):
            for page in self.pages:
                page.locator(select.checkOut()).click()

        def hoverMenuBox(self):
            for page in self.pages:
                page.locator(select.hoverBox()).hover()

        def clickLogout(self):
            for page in self.pages:
                page.locator(select.logoutUser()).click()

        def getSuccessStatus(self):
            for page in self.pages:
                set_test_status(page, "passed", "Success")

        def getFailed(self):
            for page in self.pages:
                set_test_status(page, "failed", "Test failed")

        def closeBrowser(self):
            for browser in self.browsers:
                browser.close()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;em&gt;FileName *&lt;/em&gt;— testScenarios / parallelLoginBuyRun.py:*&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
    sys.path.append(sys.path[0] + "/..")

    from testScripts.parallelLoginBuyScript import LoginAndBuy
    from playwright.sync_api import sync_playwright


    with sync_playwright() as playwright:
        try:
            playwright = LoginAndBuy(playwright)
            playwright.launchWeb()
            playwright.fillEmail("some3gmail@gmail.com")
            playwright.fillPassword("mypassword")
            playwright.clickLogin()
            playwright.fillSearchBox("Nikon")
            playwright.clickSearchButton()
            playwright.clickProduct()
            playwright.clickAddToCart()
            playwright.clickCheckOutModal()

            playwright.hoverMenuBox()
            playwright.clickLogout()
            playwright.getSuccessStatus()
        except:
            playwright.getFailed()
        playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6s0gn4HBN3sWHpA0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6s0gn4HBN3sWHpA0.png" width="156" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright Python Code Walkthrough:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FileName — testScripts / parallelLoginBuyScript.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We start by importing all necessary modules for the test case inside the &lt;strong&gt;parallelLoginBuyScript.py&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   from playwright.sync_api import sync_playwright
        import sys
        sys.path.append(sys.path[0] + "/..")

        from elementSelectors.loginAndBuySelectors import elementSelector
        from testCapabilities.testCaps import testCapabilities

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is an instance of the &lt;strong&gt;elementSelector&lt;/strong&gt; and &lt;strong&gt;testCapabilities&lt;/strong&gt; classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  select = elementSelector()

        capability = testCapabilities()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then set up the test status function to trigger failed or success messages on the cloud grid UI. Remember, we’ll implement this as a method of the &lt;strong&gt;loginAndBuy&lt;/strong&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def set_test_status(page, status, remark):
                page.evaluate("_ =&amp;amp;gt; {}",
                "lambdatest_action: {\"action\": \"setTestStatus\", \"arguments\": {\"status\":\"" + status + "\", \"remark\": \"" + remark + "\"}}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;loginAndBuy&lt;/strong&gt; inherits the Playwright class methods. As you can see, the &lt;strong&gt;&lt;strong&gt;init&lt;/strong&gt; **function accepts an extra **playwright&lt;/strong&gt; argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    class LoginAndBuy:
            def __init__(self, playwright) -&amp;amp;gt; None:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to iterate through the browser capabilities, then instantiate a browser context for each. Thus, the &lt;strong&gt;self.pages&lt;/strong&gt; attribute inherits the &lt;strong&gt;pages&lt;/strong&gt; list created from the loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def __init__(self, playwright) -&amp;amp;gt; None:
                self.allCaps = [capability.Edge(), capability.Chrome()]
                self.browsers = [playwright.chromium.connect(i) for i in self.allCaps]
                pages = [i.new_page() for i in self.browsers]
                self.pages = pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we launch the test website on both browser contexts inside a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def launchWeb(self):
                for page in self.pages:
                    page.goto(select.webPage())
                    title = page.title()
                    print(title)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the methods in the class take an event handler, which we’ll run inside another file in an event loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  def fillEmail(self, data):
                for page in self.pages:
                    page.locator(select.eMail()).fill(data)

            def fillPassword(self, data):
                for page in self.pages:
                    page.locator(select.Password()).fill(data)

            def clickLogin(self):
                for page in self.pages:
                    page.locator(select.loginAccount()).click()

            def fillSearchBox(self, data):
                for page in self.pages:
                    page.locator(select.searchProduct()).fill(data)

            def clickSearchButton(self):
                for page in self.pages:
                    page.locator(select.searchButton()).click()

            def clickProduct(self):
                for page in self.pages:
                    page.locator(select.Product()).click()

            def clickAddToCart(self):
                for page in self.pages:
                    page.locator(select.addCart()).click()

            def clickCheckOutModal(self):
                for page in self.pages:
                    page.locator(select.checkOut()).click()

            def hoverMenuBox(self):
                for page in self.pages:
                    page.locator(select.hoverBox()).hover()

            def clickLogout(self):
                for page in self.pages:
                    page.locator(select.logoutUser()).click()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also declare the test status functions as methods under the &lt;strong&gt;loginAndBuy&lt;/strong&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   def getSuccessStatus(self):
                for page in self.pages:
                    set_test_status(page, "passed", "Success")

            def getFailed(self):
                for page in self.pages:
                    set_test_status(page, "failed", "Test failed")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we iterate through the browser contexts to close the opened instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    def closeBrowser(self):
                for browser in self.browsers:
                    browser.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FileName — testScenarios / parallelLoginBuyRun.py:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We import all the essential packages in the parallel test runner file. However, the custom class of interest this time is &lt;strong&gt;loginAndBuy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import sys
        sys.path.append(sys.path[0] + "/..")

        from testScripts.parallelLoginBuyScript import LoginAndBuy
        from playwright.sync_api import sync_playwright

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;playwright_sync&lt;/strong&gt; event loop runs the parallel test case, starting with a &lt;strong&gt;playwright&lt;/strong&gt; instance of the &lt;strong&gt;loginAndBuy&lt;/strong&gt; class, followed by website launch on both browser contexts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    with sync_playwright() as playwright:
            try:
                playwright = LoginAndBuy(playwright)
                playwright.launchWeb()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Fill out the login form and sign in on both browser contexts considered for the parallel test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.fillEmail("some3gmail@gmail.com")
        playwright.fillPassword("mypassword")
        playwright.clickLogin()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: Search for a product and click the search button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; playwright.fillSearchBox("Nikon")
        playwright.clickSearchButton()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Go to the product page by clicking it once found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    playwright.clickProduct()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: Add the product to the cart by clicking the &lt;strong&gt;ADD TO CART&lt;/strong&gt; button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; playwright.clickAddToCart()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Check out of the product page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; playwright.clickCheckOutModal()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt;: Log out of the website and return a success status on the LambdaTest cloud grid UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   playwright.hoverMenuBox()
        playwright.clickLogout()
        playwright.getSuccessStatus()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the test fails for whatever reason, the &lt;strong&gt;getFailed()&lt;/strong&gt; method within the &lt;strong&gt;except&lt;/strong&gt; block runs and returns a failed message on the grid UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    except:
                playwright.getFailed()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s also important to close the event loop for each browser context to prevent an endless loop. We do this outside the &lt;strong&gt;try-except&lt;/strong&gt; block to avoid termination conflict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  playwright.closeBrowser()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Execution of the Login and Purchase Parallel Test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the &lt;strong&gt;parallelLoginBuyRun.py&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python parallelLoginBuyRun.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is the parallel test execution for the selected browser on the cloud grid:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A2sGoclRtS_0VIdSG.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A2sGoclRtS_0VIdSG.jpg" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Check this out: Test On &lt;a href="https://www.lambdatest.com/android-emulator-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=dec22_sd&amp;amp;utm_term=sd&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Online Emulator Android&lt;/a&gt;- Test your web and mobile apps on Android Emulators online.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Playwright testing framework provides simple methods for end to end testing. In this article, we demonstrated the use of Playwright Python for single and parallel testing. And we wrapped all our test cases inside the POM model for simplicity.&lt;/p&gt;

&lt;p&gt;We started by exploring the power of Playwright’s code generator and how it can help us automatically create test case code and selectors. But since that method is complex and unscalable, we further implemented a single custom end to end Playwright test on user registration and product purchase on the LambdaTest e-commerce playground.&lt;/p&gt;

&lt;p&gt;This led us to perform a cross-browser parallel test for a similar test scenario. And you’ve also seen how to create class methods that connect your tests to the LambdaTest cloud grid.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
