Table of contents:
- Understanding the Role of Selenium ChromeDriver in Test Automation
- Setting Up Selenium ChromeDriver for Automated Testing
- Controlling the Lifetime of Selenium ChromeDriver in Test Sessions
- Best Practices for Managing Selenium ChromeDriver in Testing Environment
- Dealing with Common Challenges in Using Selenium ChromeDriver for Test Automation
- Strategies to Optimize Selenium ChromeDriver Usage in Test Automation
- Case Study: Effective Use of Selenium ChromeDriver in Real-World Test Automation Scenarios
Introduction
Selenium ChromeDriver plays a crucial role in automating web application testing, serving as a bridge between Selenium commands and actions in the Chrome browser. With its ability to script tests in various programming languages and execute them on Chrome, ChromeDriver enables the evaluation of web applications for functionality, compatibility, and responsiveness. Acquiring a comprehensive understanding of ChromeDriver's usage is vital for running effective Selenium WebDriver tests on Google Chrome.
In this article, we will explore the role of Selenium ChromeDriver in test automation and delve into strategies to optimize its usage. We will discuss best practices for managing ChromeDriver in testing environments, tackling common challenges, and enhancing test execution efficiency. Furthermore, we will examine real-world case studies that demonstrate the effective use of Selenium ChromeDriver in test automation scenarios. By following these insights and techniques, developers can harness the power of Selenium ChromeDriver to improve the efficiency and reliability of their automated tests
1. Understanding the Role of Selenium ChromeDriver in Test Automation
Selenium ChromeDriver is a cornerstone in automating web application testing, serving as a bridge that translates Selenium commands into actions for the Chrome browser. It's a potent tool, enabling scripting tests in any supported programming language, including Java, and executing them on the Chrome browser. This functionality is key when evaluating web applications for functionality, compatibility, and responsiveness.
Acquiring a comprehensive understanding of ChromeDriver's usage for running Selenium WebDriver tests on Google Chrome is vital. The process starts with downloading the ChromeDriver executable file that matches your Chrome browser version. It's important to set the path of the ChromeDriver executable in your test script, creating an instance of the ChromeDriver class, and using its methods for browser automation[^1^].
These operations are achievable using software development environments like Eclipse, involving the creation and execution of Selenium codes, the addition of dependencies, and the importation of jars[^1^].
Dealing with browser-specific alerts, common on websites like Facebook and Flipkart, is manageable using the ChromeOptions class. The class includes methods that enable various ChromeDriver capabilities. For instance, the ChromeOptions.addArguments("disable notifications") method disables notifications in the Chrome browser[^1^].
Selenium WebDriver, an open-source automation tool, empowers developers to construct robust web applications by automating web browsers. It supports a variety of programming languages such as Java, Python, and C, allowing developers to script in their preferred language[^1^].
The WebDriver framework architecture consists of four main components: the Selenium client library, the JSON wire protocol over HTTP, browser drivers, and web browsers. The Selenium client library offers a programmatic interface for controlling web browsers. The JSON wire protocol defines a set of commands that can be sent over HTTP to control the web browser[^1^].
To configure a system for Selenium WebDriver, the appropriate Selenium library for the programming language in use should be downloaded and installed. The relevant web driver for the preferred browser should also be set up[^1^].
Test automation scripts with Selenium WebDriver involve converting test commands into HTTP requests using the JSON wire protocol, initializing the browser driver, executing test commands through the driver, and capturing and comparing the results[^1^].
Selenium ChromeDriver can be debugged using the Chrome DevTools Protocol. This protocol allows interaction with the Chrome browser and access to its debugging features. Commands provided by the protocol can be used to control the browser, navigate through pages, interact with elements, and debug JavaScript code[^4^].
Platforms like Headspin can enhance Selenium WebDriver capabilities by offering browser and platform coverage, simulating real user conditions, enabling device interaction and sensor simulation, providing advanced debugging and monitoring features, supporting test execution at scale, integrating with test frameworks, and offering detailed reporting and analysis[^1^].
When working with Selenium and the Chrome browser, several common issues can arise with the Selenium ChromeDriver. These include compatibility problems, version mismatches, and configuration errors. Ensuring the version of the ChromeDriver in use is compatible with the installed Chrome version is crucial, as is verifying that the ChromeDriver executable is correctly configured and accessible in your system's PATH variable[^7^].
To integrate Selenium ChromeDriver with test frameworks, follow these steps:
- Install the necessary dependencies, including Selenium WebDriver and the ChromeDriver executable.
- Set the system property for ChromeDriver, specifying the location of the ChromeDriver executable file before launching the WebDriver.
- Create a new instance of the ChromeDriver using the constructor of the ChromeDriver class.
- Configure the test framework to use the ChromeDriver, which often involves setting the path to the ChromeDriver executable and specifying the desired capabilities.
- Write your test cases using the Selenium WebDriver API. This allows for interaction with web elements, performing actions, and making assertions to verify your web application's behavior[^9^].
By following these steps, Selenium ChromeDriver can be integrated with your chosen test framework, enabling automation of your web tests[^9^]
2. Setting Up Selenium ChromeDriver for Automated Testing
The configuration of Selenium ChromeDriver for automated testing incorporates several critical steps. Initially, it's necessary to download the correct version of ChromeDriver, which can be procured from the official Selenium website. This process involves opening a browser, navigating to the Selenium website, locating the relevant section for Selenium driver downloads, and downloading the appropriate version of ChromeDriver for your operating system. Once downloaded, the contents must be extracted to a suitable location on your computer.
It's essential to ensure that the ChromeDriver version aligns with the Chrome browser installed on your system. This involves checking the release notes of the ChromeDriver to find the version compatible with your installed Chrome browser. The downloaded ChromeDriver executable must be placed in a directory included in your system's PATH. Alternatively, the path to the ChromeDriver executable can be specified directly within the test script.
When using Java, the System.setProperty()
method can be employed to specify the ChromeDriver executable path in your test script. For instance, the code System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
can be used, replacing "path/to/chromedriver" with the actual path to the ChromeDriver executable on your machine.
ChromeDriver, maintained by the Chromium team and WebDriver contributors, is a separate executable controlled by Selenium WebDriver. It is a pivotal tool for testing websites on desktop platforms like Windows, Mac, and Linux. It requires Chrome to be installed in your platform's default location for test setup. To enhance flexibility, a custom location for ChromeDriver can be specified by setting a special capability.
Running large test suites where a ChromeDriver instance is created per test often entails the use of the ChromeDriverService. This service can be used to manually start and stop the ChromeDriver server. Alternatively, the ChromeDriver server can be started separately before executing your tests, and then connected to it using the remote WebDriver.
ChromeDriver is a standalone server used by Selenium WebDriver to control Chrome. It can be configured via environment variables or by explicitly specifying the path in the test script. Tools like BrowserStack can be leveraged to perform cross-browser testing on Safari, Opera, Edge, and other browsers.
Given Google Chrome's global market share of 64% and over 98 versions of the Chrome browser available for testing, the importance of ChromeDriver in running Selenium tests on the Chrome browser is paramount. This highlights the necessity for a careful setup process to ensure that automated testing functions seamlessly and effectively.
To set up Selenium ChromeDriver, it's beneficial to follow a few best practices. These include ensuring you have the correct ChromeDriver version that matches your Chrome version, adding the ChromeDriver executable to your system's PATH, using WebDriverManager for automatic driver management, and configuring necessary options or capabilities such as setting the browser window size or enabling headless mode.
Moreover, troubleshooting common issues with Selenium ChromeDriver setup may involve verifying the ChromeDriver version, ensuring the executable is added to your system's PATH, checking file permissions, looking for conflicts with other software, and ensuring network and firewall settings are correctly configured for remote servers or virtual environments.
Finally, the setup of ChromeDriver varies slightly across different operating systems. For Windows, the extracted executable file needs to be added to the system's PATH. For macOS and Linux, the extracted file needs to be made executable using chmod +x chromedriver
in the Terminal, and moved to a location in the PATH. These steps ensure a smooth and efficient setup of Selenium ChromeDriver for your automated testing needs
3. Controlling the Lifetime of Selenium ChromeDriver in Test Sessions
The importance of effectively managing the lifespan of Selenium ChromeDriver instances in automation testing is crucial. It is a common practice to start a fresh ChromeDriver instance at the beginning of each test and dispose of it at the conclusion. This process is key to ensuring that each test runs in a clean, isolated environment, significantly reducing the likelihood of cross-test interference.
In Java, the creation of the ChromeDriver instance is usually carried out within a setup method, denoted with the @Before annotation, whereas, the disposal of the instance is handled within a teardown method, marked by the @After annotation.
```java import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver;
public class ChromeDriverExample { public static void main(String[] args) { // Set the path of the chromedriver executable System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
// Create a new instance of ChromeDriver
WebDriver driver = new ChromeDriver();
// Perform automation tasks
driver.get("https://example.com");
// ...
// Dispose of the ChromeDriver instance
driver.quit();
}
} ```
The Selenium software project provides a well-structured framework for automating web browsers, including components such as WebDriver, HTTP client service, and remote WebDriver. This framework supports a range of browsers like Chrome, Edge, Firefox, Internet Explorer, and Safari. The Selenium Grid feature allows for parallel execution and distributed testing, enhancing the efficiency of test automation.
Following best practices can help achieve efficient test automation with Selenium and ChromeDriver. It's important to use a stable and compatible version of ChromeDriver that matches the version of the Chrome browser in use. Optimizing test scripts by using appropriate wait strategies, such as explicit waits, can ensure that the elements on a page are fully loaded before interacting with them. Implementing a robust test framework that supports parallel execution of tests allows for multiple tests to run simultaneously, saving time.
Applying the Page Object Model (POM) design pattern can help create reusable and maintainable test scripts by separating the test logic from the page elements, making it easier to maintain and update tests. Using data-driven testing techniques to execute tests with different input data sets can maximize test coverage and efficiency. Implementing proper error handling and reporting mechanisms can help identify and debug issues quickly.
Setting up a continuous integration (CI) pipeline to automate the execution of tests on every code commit ensures that tests are always up-to-date and provides quick feedback on any failures.
To minimize test interference with ChromeDriver instance management, it's critical to ensure proper cleanup by closing and quitting the ChromeDriver instance after each test case. This helps in releasing system resources and avoiding interference between subsequent test cases. Implementing synchronization mechanisms can ensure that tests are executed in a controlled manner, preventing multiple tests from accessing the ChromeDriver instance simultaneously.
By using techniques such as virtualization or containerization, you can create separate environments for each test case, ensuring that they do not interfere with each other. Tools like Docker can create lightweight containers that encapsulate the necessary dependencies, including Selenium ChromeDriver. Each test case can run in its own isolated environment, ensuring that any changes or dependencies in one test case do not affect the others.
By following these best practices and techniques, you can achieve efficient test automation with Selenium and ChromeDriver, improving the reliability and speed of your test execution
4. Best Practices for Managing Selenium ChromeDriver in Testing Environment
Selenium ChromeDriver's efficient management within a testing environment is a crucial aspect of effective test automation. One key aspect is the consistent updating of ChromeDriver, as outdated versions can potentially create compatibility issues with the latest versions of the Chrome browser.
To update Selenium ChromeDriver for compatibility with newer versions of the Chrome browser, it is advisable to follow the steps below:
- Identify the current version of the Chrome browser in use.
- Visit the official Selenium website or the ChromeDriver website to find the latest version of ChromeDriver that is compatible with your Chrome browser version.
- Download the latest version of ChromeDriver.
- Replace the existing ChromeDriver executable file with the newly downloaded version.
- Restart the Selenium test environment.
By adhering to these steps, you can ensure that your Selenium ChromeDriver is updated and compatible with the newer versions of the Chrome browser.
Exception handling is another critical element in script writing. Unhandled exceptions may result in ChromeDriver instances not shutting down correctly, disrupting the testing process. To implement exception handling strategies for ChromeDriver in Selenium test scripts, try-catch blocks can be utilized. By encapsulating the specific code that may throw exceptions in a try block, you can catch and handle any exceptions that occur in the catch block. This allows for graceful handling of any errors or unexpected behavior that may arise during the execution of your test scripts. Also, the WebDriverException class provided by Selenium can be used specifically to handle exceptions related to ChromeDriver.
The use of explicit waits over implicit waits is highly recommended in Selenium tests with ChromeDriver. Explicit waits provide a more dependable method of dealing with asynchronous operations within tests. This is primarily due to their ability to wait for specific conditions to be met before proceeding, which reduces the risk of false positives or skipped tests.
To manage asynchronous operations in Selenium tests with explicit waits and ChromeDriver, the WebDriverWait class provided by Selenium can be used. WebDriverWait allows for the test to wait for a certain condition to be met before proceeding with the test execution. This can be helpful when dealing with elements that may take some time to load or become interactive.
The Selenium ecosystem offers tools like Selenium Manager that can enhance ChromeDriver management. This tool facilitates automatic configuration of browser drivers for Chrome, Firefox, and Edge. It operates as a command-line interface developed in Rust and can be invoked by Selenium bindings when no browser driver is detected or a third-party driver manager is not in use.
ChromeDriver is a standalone server that allows Selenium WebDriver to control Chrome, making it an integral part of automating browser actions like navigating to a URL or filling out a form. Platforms such as BrowserStack offer more than 3000 real devices and browsers for testing, including different versions of the Chrome browser. This platform provides solutions for mobile app testing, web testing, accessibility testing, and test management, thereby enhancing the user experience and ensuring comprehensive testing capabilities.
In essence, effective management of Selenium ChromeDriver in a testing environment involves keeping the ChromeDriver up-to-date, handling exceptions appropriately, using explicit waits, and leveraging tools such as Selenium Manager and platforms like BrowserStack
5. Dealing with Common Challenges in Using Selenium ChromeDriver for Test Automation
The Selenium ChromeDriver's capabilities in automated testing are robust, yet they are not without their challenges. For instance, managing dynamic web elements can prove challenging, as it can lead to test failures if not appropriately addressed. Further complications arise in managing test data, especially with the increasing complexity of web applications. Ensuring the reliability and repeatability of tests, particularly in the face of asynchronous operations and varying network conditions, is another hurdle to overcome.
The good news is that a systematic approach can make these challenges manageable. This approach includes consistent coding conventions in Selenium ChromeDriver automation, such as the use of PascalCase for method and class names, and camelCase for local variables and parameters. It's also best to avoid abbreviations and underscores in naming conventions.
Adhering to the DRY principle, which stands for "Don't Repeat Yourself," is another essential practice. It encourages the elimination of code duplication by creating setup methods for common actions and using variables for web elements, thereby avoiding the need to repeatedly search for them.
Writing independent tests that do not rely on each other is of paramount importance. Creating test data in one test for another can lead to unexpected failures and debugging difficulties.
The Single Responsibility Principle is also crucial. It means that classes should only have one reason to change. In the context of test automation, this means creating short tests that focus on a single functionality and separating preconditions and cleanup actions into setup and teardown methods.
To optimize testing, it's advisable to limit the number of assertions in a test to one or two at most. If multiple assertions are needed, consider splitting the large test into smaller, more focused tests.
When it comes to locator strategy, options available in Selenium ChromeDriver include ID, CSS selector, XPath, and class name. The ID strategy is the most recommended, followed by class name and CSS selector.
The use of wait methods in Selenium WebDriver is recommended over the use of Thread.Sleep. These wait methods can be divided into implicit waits, which apply to all elements, and explicit waits, which apply to specific elements.
In terms of design patterns, the Page Object Model (POM) is highly recommended for UI test automation. This involves separating UI interaction methods into separate classes that represent web pages or components and calling these methods from test classes.
To maintain a clean design, assertions should be kept out of page object classes. Instead, boolean values should be returned for validation in test classes. Similarly, Selenium methods should not be used directly in test classes; they should be encapsulated in page object classes.
For debugging purposes, it's beneficial to take screenshots of failed steps in tests. Selenium's GetScreenshot method and the TestProject SDK's ability to take screenshots can be useful in this regard.
Finally, using a robust reporting tool is essential for demonstrating test results. Test reports can help track test progress and compare results between runs.
By adhering to these best practices, the challenges associated with Selenium ChromeDriver can be effectively addressed, leading to more efficient and reliable test automation. However, let's delve deeper into some of these points.
To handle dynamic web elements in Selenium with ChromeDriver, you can utilize XPath to locate elements using their attributes, text, or even their position in the HTML structure. CSS selectors can also be used to target dynamic elements based on their attributes, classes, or other properties. Explicit waits can also be employed to wait for dynamic elements to be visible, clickable, or have specific attributes before interacting with them. In certain scenarios where Selenium is unable to interact with a dynamic element, JavaScriptExecutor can be used to execute JavaScript code and manipulate the element directly.
When dealing with varying network conditions in Selenium Chromedriver tests, the network emulation feature provided by Chromedriver allows you to simulate different network conditions such as slow connection speeds, high latency, or even offline mode. This can be helpful in identifying and fixing any performance issues or bugs that may arise due to varying network conditions.
To ensure reliability and repeatability in Selenium ChromeDriver tests, it's crucial to follow best practices for Java unit testing. This includes using proper annotations and assertions, as well as implementing techniques such as test data management and test environment setup and teardown. Additionally, using a stable and up-to-date version of Selenium ChromeDriver, as well as maintaining a consistent test environment configuration, can improve the reliability and repeatability of your Selenium ChromeDriver tests.
These are just some of the ways in which you can tackle the challenges associated with Selenium ChromeDriver and lead to more efficient and reliable test automation
6. Strategies to Optimize Selenium ChromeDriver Usage in Test Automation
Optimizing Selenium ChromeDriver in test automation can significantly enhance the efficiency and reliability of tests. One of the strategies to achieve this is by employing the Page Object Model (POM). As a design pattern, POM fosters code maintainability and reusability. It segregates the test code from the actual web elements and actions on a web page, allowing for easier maintenance and updates to the test code. Any changes to web elements or actions can be made in one place, the page object, rather than throughout the entire test code. This separation promotes code reusability, as multiple tests can leverage the same page object, reducing code duplication.
Another strategy to optimize test execution is parallel execution. This method curtails the overall test execution time by running multiple tests simultaneously. Testing frameworks like TestNG and JUnit offer robust support for parallel execution in test automation. TestNG provides different parallel execution modes such as methods, classes, and suites. You can configure the parallel mode in the testng.xml file or programmatically using annotations. JUnit, on the other hand, introduced the concept of parallel test execution using the @RunWith(Parameterized.class) annotation in JUnit 4, and expanded on it in JUnit 5 with the @Execution and @Parallel annotations. However, when designing test cases for parallel execution, it's important to consider any dependencies or shared resources to ensure correct and reliable execution.
In addition to these strategies, the use of headless mode can significantly expedite test execution. This mode allows tests to run without the need for a browser's graphical user interface, which in turn speeds up the testing process.
The optimization of Chrome browser options for testing can also result in a substantial enhancement in the speed of browser tests. By adjusting various Chrome options, including disabling certain features and enabling automation, one can significantly improve the performance of automated tests. However, it's crucial to evaluate their effect on the specific test environment and application behavior as not all options may be relevant to every testing scenario.
The client-side part of Selenium-based browser automation also necessitates efficiency. Each command sent to the browser corresponds to a separate HTTP REST API call, and a set of commands sent to the same browser is referred to as a "browser session". This Selenium architecture has evolved over time, with the introduction of independent standalone executable files called web drivers for different browser types, leading to the creation of Selenium WebDriver.
There are two primary groups of Selenium client libraries: WebDriver protocol clients and WebDriver-based tools. WebDriver protocol clients are thin wrappers around WebDriver protocol HTTP calls, while WebDriver-based tools provide higher-level libraries for more efficient browser automation. However, existing Selenium client libraries can have limitations, such as poor support for user authentication methods, overcomplicated browser startup, and confusing API for certain operations. To overcome these limitations, new client implementations like "Lightning" have been introduced. Lightning is a Java client implementation for WebDriver protocol that aims to be lightweight and fast. It uses the built-in Java 11 HTTP client and the Jackson library for JSON processing, thereby providing a more efficient tool for browser automation
7. Case Study: Effective Use of Selenium ChromeDriver in Real-World Test Automation Scenarios
Automated testing is a pivotal aspect of software development, playing a crucial role in ensuring the functionality and reliability of web applications. To illustrate, consider the transformative power of automated testing tools as demonstrated by JW Player, a globally recognized online video player. JW Player's previous testing approach involved an open-source Ruby framework on top of Cucumber. However, this approach faced certain limitations, particularly in terms of performance and lack of support from product engineers due to its Ruby-based framework.
Taking these challenges into account, JW Player migrated to WebdriverIO, an automated testing solution known for its user-friendly API, extensive browser and device support, rich plugin system, and active developer community. This shift was not merely a change in tools but a strategic decision that led to significant enhancements in JW Player's testing processes.
The integration of existing tools like Allure reporting and Report Portal was seamless with WebdriverIO. Additionally, the features offered by WebdriverIO, such as network primitives and Chrome DevTools Protocol support, enabled JW Player to simplify its codebase, eliminate dependencies, and automate complicated tests that were previously manual tasks.
As a result, JW Player saw a considerable improvement in performance and shorter regression cycles. The migration led to the discovery of a higher number of defects, contributing to a better quality product. This real-life example emphasizes the impact of effective test automation tools in enhancing software quality and reliability.
In the same vein, Roku, a leading connected TV (CTV) device in the United States, introduced Roku WebDriver in December 2019. This official solution for Roku test automation significantly improved the testing capabilities for Roku channels, which are developed using a language called BrightScript. Roku WebDriver provided an HTTP server solution for querying the status of Roku devices and sending remote commands via ECP (External Control Protocol).
The release of Roku's WebDriver API significantly paved the way for effective UI test automation, despite the resources being relatively new and potentially requiring further extension. Automating tests on Roku has proven invaluable in providing fast and comprehensive feedback for identifying defects. Additionally, test automation reduces the effort required for manual regression testing, paving the way for more efficient and comprehensive testing.
These real-world examples underscore the transformative power of automated testing tools in enhancing software quality and reliability. Therefore, it's paramount for software development teams to carefully select and implement automated testing tools that best suit their specific needs and challenges.
When adopting web application testing automation using Selenium Chromedriver, it's beneficial to keep certain points in mind. First, using a reliable and up-to-date version of Selenium Chromedriver ensures compatibility with the web browser you are testing. Writing clear and maintainable test scripts using a programming language such as Java or Python allows for easier debugging and maintenance of the test scripts. Furthermore, it's crucial to use proper element locators to identify and interact with web elements. CSS selectors and XPath can be used to locate elements accurately.
Additionally, implementing waits in your test scripts to handle dynamic elements and ensure that the page is fully loaded before performing any actions helps to avoid flaky tests. The Page Object Model (POM) design pattern can be utilized to organize your test scripts. This separates the test logic from the page structure, making the code more modular and easier to maintain. Error handling and logging mechanisms can be implemented in your test scripts to assist in identifying and debugging issues during test execution.
Tests should be executed on different browsers and platforms to ensure cross-browser compatibility. Selenium Chromedriver provides support for various browsers such as Chrome, Firefox, and Safari. Integrating your test scripts with a continuous integration (CI) system such as Jenkins or Travis CI allows for automated test execution and reporting. By adhering to these tips, you can effectively automate web application testing using Selenium Chromedriver.
In conclusion, the power of automated testing tools in improving software quality and reliability is evident. The practical examples of JW Player and Roku demonstrate the transformative effects of these tools. By carefully selecting the appropriate automated testing tools and following the suggested best practices, software development teams can significantly enhance their testing processes and ultimately produce higher quality products
Conclusion
In conclusion, Selenium ChromeDriver plays a crucial role in automating web application testing by serving as a bridge between Selenium commands and actions in the Chrome browser. It enables developers to script tests in various programming languages and execute them on Chrome, allowing for the evaluation of web applications for functionality, compatibility, and responsiveness. Acquiring a comprehensive understanding of ChromeDriver's usage is vital for running effective Selenium WebDriver tests on Google Chrome. The article provides insights into best practices for managing ChromeDriver in testing environments, tackling common challenges, and enhancing test execution efficiency. Real-world case studies demonstrate the effective use of Selenium ChromeDriver in test automation scenarios.
The ideas discussed in the article have broader significance for developers and software development teams. By harnessing the power of Selenium ChromeDriver, developers can improve the efficiency and reliability of their automated tests. The techniques and best practices shared in the article offer valuable guidance for optimizing Selenium ChromeDriver usage in test automation. This can lead to faster test execution, better test coverage, and higher quality software products. It is recommended that developers explore these insights and techniques to boost their productivity and enhance their automated testing processes.
AI agent for developers
Boost your productivity with Mate. Easily connect your project, generate code, and debug smarter - all powered by AI.
Do you want to solve problems like this faster? Download Mate for free now.