How To Run Test On macOS Using Selenium Safari Driver
Tags: safari, selenium, automation, macos
Published: 2021-01-20 10:07:17

We all know that Google Chrome is the most popular browser in the world. But do you know, with [17.24%](https://gs.statcounter.com/browser-market-share) of the overall browser market share, Safari is the second most popular one?

The reason behind Safari’s strong presence is that it is the default web browser for all Apple devices. And we know how much developers and coders love macOS, making it absolutely necessary to ensure that our websites’ are tested and optimized for all Safari versions.

The latest versions of Safari (10 and above) come with _safaridriver_, an in-built option to carry out websites’ debugging. However, the earlier versions of Safari required you to install the Safari WebDriver extension, which is no longer supported in the latest versions. Safari browser instead uses the _safaridriver_ to implement WebDriver protocol.

In this blog, we will see how to use Selenium _safaridriver_ to perform testing on the Safari browser.

_ **Note:** You need to have Safari on the Mac machine, as Apple has withdrawn the support of SafariDriver from Safari browsers on Windows._

 
## Selenium Safari Driver For Automation Testing

To use the Selenium framework for automation testing, you should have a corresponding Selenium WebDriver (e.g., Chrome WebDriver for Chrome, Geckodriver for Firefox, etc.) installed on the machine. However, in [Selenium automation testing](https://www.lambdatest.com/selenium-automation?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-20012021&utm_term=Himanshu) with Safari on macOS, there is no need to download Safari driver for Selenium WebDriver separately.

Starting from Safari 10 on OS X El Capitan and macOS Sierra, the browser provides native support for the Selenium WebDriver API. As Selenium Safari driver for mac is preloaded on the OS, you need not mention the executable path for creating the Selenium WebDriver object.

### Download Safari Driver for Selenium WebDriver

As already discussed, we don’t have to download Safari’s driver for Selenium WebDriver. Instead, Safari’s in-built driver called _safaridriver_ is presently available in most Selenium client libraries. The _safaridriver_ is maintained by the web developer experience team at Apple. Apple’s _safaridriver_ executable path is /usr/bin/safaridriver. As Safari Technology Preview also provides its own executable _safaridriver_, it is a path of the application’s bundled contents.

![Selenium WebDriver](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Selenium-WebDriver.png)

The _safaridriver_ from Safari and _safaridriver_ from Safari Technology Preview can run simultaneously, as each _safaridriver_ only launches the Safari browser it is associated with.

The legacy SafariDriver which was maintained by the Selenium project, is deprecated and should not be used. In any case, Safari throws the error ‘Safari no longer supports unsafe extensions’ if you even attempt to install the deprecated Selenium WebDriver for Safari.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/image1-1.png)

For using the Selenium _safaridriver_ for automation testing, you only require Safari 10 (or later) installed on the machine since there is native support for Selenium WebDriver API in those Safari versions.

Starting from Selenium 3.0.0 release, Python and Java Client libraries offer support for native driver implementation of Safari.

### Configure Safari for enabling WebDriver Support

Even though native support for the Selenium WebDriver API is available in Safari 10 (and above), the WebDriver support is turned off by default. Follow the below-mentioned steps for enabling WebDriver support in Safari:

**macOS High Sierra (and later)**

**Step 1:** Run the following command on the terminal:

`/usr/bin/safaridriver --enable`

_ **Note:** You may need to do so in case you are upgrading from a previous macOS release._

**macOS Sierra (and earlier)**

**Step 1:** Enable the ‘Show Developer’ menu in Safari through Safari ?Preferences ? Advanced ? Select ‘Show Develop menu in menu bar’ (if it is not checked).

![macOS Sierra](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/macOS-Sierra.png)

**Step 2:** Choose Develop \> Allow Remote Automation.

![selenium safari driver](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/selenium-safari-driver.png)

**Step 3:** Now, authorize _safaridriver_ to launch the XPC service that hosts the local webserver. For this, run /usr/bin/safaridriver once and follow the authentication prompt.

As we would be using Apple’s _safaridriver_ for Selenium test automation on macOS Catalina, we would be only executing /usr/bin/safaridriver –enable (or safaridriver –enable) once on the terminal.

![safaridriver](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/safaridriver.png)


## Salient Features Of Selenium Safari Driver On macOS

For supporting WebDriver without sacrificing user’s privacy and security, there are additional safeguards that ensure that Selenium test execution is completely isolated from normal browsing data and other test runs.

Here are some of the salient features of Selenium Safari driver on macOS:

### Feature #1: Isolated Automation Windows

The _safaridriver_ developed by Apple’s web developer experienced team ensures that the test execution and Selenium test automation scenarios are confined to special automation windows. This means that the tests being executed using the safari driver will be isolated from normal browsing windows, user settings, and preferences.

Like automation testing performed using _geckodriver_ (for Firefox), Safari windows on which tests are being executed can be identified by their orange Smart Search field.

![Isolated Automation](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Isolated-Automation.png)

Like a private browsing session in Safari, automation tests using Apple’s _safaridriver_ start afresh so that the previous test session’s persistent state does not have any implications on the newly fired Selenium test automation scenario.

### Feature #2: Web Inspector

Web Inspector (or Inspect) tool can be used during and after the Selenium WebDriver test’s execution. Features such as locating details about web elements, monitoring network performance, recording performance, etc., in Web Inspector are completely functional when Selenium test automation scenarios are being executed.

The option Develop \> Show Web Inspector menu item launches the inspection tool when the Selenium WebDriver tests are running.

### Feature #3: Selenium WebDriver commands for debugging

Selenium Safari driver on macOS lets you specify WebDriver capabilities in a New Session for debugging.

The _safaridriver_ preloads Web Inspector and JavaScript debugger in the background when the Safari:automaticInspection capability is passed in a New Session request. Like the Inspect tool, you also have the option to pause the test execution for checking the execution details in the Debugger tab of Web Inspector.

The _safaridriver_ preloads Web Inspector and starts timeline recording in the background when the Safari:automaticProfiling capability is passed in a New Session request. The details can be viewed in the Timeline tab of the Web Inspector.

### Feature #4: Glass Pane

A Glass Pane is installed over the Safari window, where the execution of the automation test is in progress. The glass pane intends to block any interactions such as a mouse, keyboard, resizing, closing, minimizing, etc., that can be performed manually and can hinder the test being performed in the Automation Window.

However, there is a way to break the glass pane if the test in progress is stuck (or failed) or you want to check something in the automation window manually. Once the glass pane is broken, the Selenium test automation session is interrupted, and the automation window continues to remain open for further inspection until it is closed manually.

Shown below is the popup window which comes up when we try to break the WebDriver Session:

- **Turn off All Automation –** This option will disable ‘Develop \> Allow Remote Automation,’ enabled for using Selenium Safari driver in macOS for running automation tests.  
The command `safaridriver –enable` has to be rerun on the terminal if you want to run tests in the Safari browser.
- **Stop Session –** This option stops the current WebDriver session, and you can continue to interact with the browser.
- **Continue Session –** This option continues the session, i.e., the test is run from the point where it was paused. Once this option is selected, you would not be able to interact with the browser.

### Feature #5: Only one session at a time

At a time, you can only attach one WebDriver session to the instance of the Safari browser. Hence, only one Safari instance and WebDriver session attached to it can be active during automation testing.

As per [Apple’s official blog](https://developer.apple.com/documentation/webkit/about_webdriver_for_safari), these constraints prevent the tests from internally competing with each other for resources like window focus, keyboard events, keyboard focus, and more. It also reflects what you can do in a macOS, windowing environment.

## Testing With Selenium Safari Driver On macOS

Now that we have set up Apple’s Safari driver, we look at the process of setting up Selenium WebDriver on macOS and running a test in Python. When a test scenario calls a Selenium command, the command is executed in the following manner:

1. Every Selenium command is translated into a REST API command by the client library.
2. The REST API command sends the HTTP request to the local web server that is hosted by Apple’s _safaridriver_.
3. The _safaridriver_ validates the HTTP request contents, and the command is forwarded to the browser instance.
4. Once the command execution is complete, the _safaridriver_ sends an HTTP response, which the client library interprets. The corresponding result is returned to the test code.

![Selenium Safari-driver](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Selenium-Safari-driver.png)

Let’s look at a cross browser testing scenario that showcases Selenium Safari’s driver on macOS demonstration. Here is the test scenario:

- Go to the URL https://lambdatest.github.io/sample-todo-app/.
- Select the first two options.
- Send ‘Happy Testing at LambdaTest’ to the textbox with id = sampletodotext.
- Click the ‘Add Button’ and verify the added text.

We would be using the PyTest framework for the demonstration. For a quick recap about PyTest, you can refer to this detailed [Selenium WebDriver tutorial](https://www.lambdatest.com/blog/test-automation-using-pytest-and-selenium-webdriver/?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-20012021&utm_term=Himanshu). You can install PyTest on macOS by triggering the command pip install pytest on the terminal.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Selenium-WebDriver-tutorial.png)

### Implementation

```python
import pytest
from selenium import webdriver
@pytest.fixture(scope="class")
 
def driver_init(request):
    web_driver = webdriver.Safari()
    request.cls.driver = web_driver
    yield
    web_driver.close()
```
 
### Code WalkThrough

A new browser instance has to be loaded for each test. Hence, the scope of the fixture is set to class instead of the session.

```python
import pytest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
from time import sleep
import sys
 
@pytest.mark.usefixtures("driver_init")
class BasicTest:
    pass
class Test_URL_Safari(BasicTest):
    def test_lambdatest_todo_app(self):
        self.driver.get('https://lambdatest.github.io/sample-todo-app/')
        self.driver.maximize_window()
        
        self.driver.find_element(By.NAME, "li1").click()
        self.driver.find_element(By.NAME, "li2").click()
 
        title = "Sample page - lambdatest.com"
        assert title ==  self.driver.title
 
        sample_text = "Happy Testing at LambdaTest"
        email_text_field =  self.driver.find_element(By.ID, "sampletodotext")
        email_text_field.send_keys(sample_text)
        time.sleep(5)
        
        self.driver.find_element(By.ID, "addbutton").click()
        time.sleep(5)
        
        output_str =  self.driver.find_element(By.NAME, "li6").text
        sys.stderr.write(output_str)
 
        time.sleep(2)
```

**Line (9) –** The `@pytest.mark.usefixtures` is included for using the fixture `driver_init()`.

```
@pytest.mark.usefixtures("driver_init")
```

**Lines (14-15) –** Selenium WebDriver APIs are used for setting the test URL to the LambdaTest ToDo page. The browser window is maximized using the `maximize_window()` method.

```
self.driver.get('https://lambdatest.github.io/sample-todo-app/')
self.driver.maximize_window()
```

**Lines (17-18) –** The Inspect tool in Safari (or any preferred browser of your choice on macOS) can be used for locating the details of the web element.

![web element](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/web-element-1.png)

The `find_element` Selenium API is used for locating the element with NAME ‘li1’ and ‘li2’.

 
```
self.driver.find_element(By.NAME, "li1").click()
self.driver.find_element(By.NAME, "li2").click()
```

**Lines (24-27) –** The details of the web element with ID ‘sampletodotext’ are located using Safari’s Web Inspector tool. The `send_keys()` method is used to send the required string to that text box.

![element with ID](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/element-with-ID.png)


**Line (29) –** A click() operation is performed on the button with ID ‘addbutton’.

 
```
self.driver.find_element(By.ID, "addbutton").click()
``` 
 
### Execution

The execution is performed by invoking the following command on the terminal.

```
pytest -s –v test_lambdatest_todo_App.py
```

Here is the screenshot of the execution, which indicates the test did not pass!

![screenshot of the execution](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/screenshot-of-the-execution-1.png)

We’ve noticed in some of the [threads](https://stackoverflow.com/questions/58078868/selenium-tests-broken-by-recent-update-of-safari-to-version-13/58107780#58107780) on Stack OverFlow that Selenium tests are broken on Safari 13 since the click() operation does not work on Safari 13. We also tried the [workaround](https://bugs.webkit.org/show_bug.cgi?id=202589) of using Selenium JavaScript with Python on macOS Catalina; however, that also did not work.

![Selenium tests](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Selenium-tests.png)

## Testing Of Selenium Safari Driver On macOS On Cloud-Based Grid

In this section, we’ll execute the same test scenario on LambdaTest that provides a Selenium Grid on the cloud. To get started, you need to create an account on LambdaTest and note username & access-key from the [Profile page](https://accounts.lambdatest.com/detail/profile).

The test scenario will be executed on Safari 13.0, which is installed on macOS Catalina. The browser capabilities are generated using the [LambdaTest capabilities generator](https://www.lambdatest.com/capabilities-generator/?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-20012021&utm_term=Himanshu).

![Selenium-Safari Driver](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/Selenium-Safari-Driver.png)

We make the necessary changes in conftest.py to use the Remote SeleniumWebDriver instead of the local Selenium WebDriver.

### Implementation
 
```python
import pytest
from selenium import webdriver
import urllib3
 
saf_capabilities = {
        "build" : "Safaridriver on MacOs Catalina",
        "name" : "Safaridriver on MacOs Catalina",
        "platform" : "MacOS Catalina",
        "browserName" : "Safari",
        "version" : "13.0"
}
 
user_name = "user-name-not-email-address"
app_key = "access-key"
 
@pytest.fixture(scope="class")
 
def driver_init(request):
    # web_driver = webdriver.Safari()
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    remote_url = "http://" + user_name + ":" + app_key + "@hub.lambdatest.com/wd/hub"
    web_driver = webdriver.Remote(command_executor = remote_url, desired_capabilities = saf_capabilities)
    request.cls.driver = web_driver
    yield
    # web_driver.close()
    web_driver.quit()
```

The implementation in test\_lambdatest\_todo\_App.py remains unchanged since that is independent of the Selenium Grid infrastructure.

### Code WalkThrough

**Line (21) –** The combination of user-name and access-key are used for accessing the LambdaTest Grid URL [@hub.lambdatest.com/wd/hub]

 
```
remote_url = "https://" + user_name + ":" + app_key + "@hub.lambdatest.com/wd/hub"
```

**Line (22) –** The Selenium WebDriver API uses the LambdaTest Grid URL and browser capabilities (i.e. saf\_capabilities) that were generated using the LambdaTest Capabilities Generator.

 
```
web_driver = webdriver.Remote(command_executor = remote_url, desired_capabilities = saf_capabilities)
```
 
 
### Execution

The following command is used for triggering the test on cloud-based Selenium Grid on LambdaTest.

```
pytest –v -s test_lambdatest_todo_App.py
```

Here is the screenshot of the execution, which indicates that the click operation is working as required on the LambdaTest Grid:

![cloud-based Selenium](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/cloud-based-Selenium.png)

![cloud-based Selenium](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/cloud-based-Selenium-1.png)

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/image13-2.png)


## Wrapping up

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/11/unnamed.jpg)

Setting up Apple’s _safaridriver_ on Mac is hassle-free and straightforward since it does not require installing the _safaridriver_. Despite the simplicity associated with Selenium Safari driver on macOS, there are issues with events such as click, which does not work when used in Selenium automation testing. In case you do not own a device with macOS on it, there is always an option to install macOS on a virtual machine and try out Apple’s Safari driver for Selenium test automation.

The issues observed with testing using Apple’s Safari driver on the local copy of macOS are not observed with Selenium test automation on cloud-based [Selenium Grid](https://www.lambdatest.com/selenium-automation?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-20012021&utm_term=Himanshu) by LambdaTest. Along with proper (or expected) output, it results in expediting the process of automation testing.