---
title: Selenium GitHub Action for TestingBot
description: The TestingBot GitHub Action allows you to run WebDriver tests with GitHub
  Actions.
source_url:
  html: https://testingbot.com/support/integrations/ci-cd/github-actions
  md: https://testingbot.com/support/integrations/ci-cd/github-actions/index.md
---
# TestingBot GitHub Action

This guide will help you integrate the TestingBot GitHub Action workflow in your project.   
 The TestingBot GitHub action provides an action to integrate the [TestingBot Tunnel](https://testingbot.com/support/tunnel) in your tests.   
The TestingBot Tunnel is used to route all test traffic between your web application and the TestingBot browser/device cloud.

The GitHub action will also save the [test-artifacts](https://testingbot.com#artifacts) for you, so that you can later see the meta-data generated by the test.

## GitHub Secrets

To get started, you'll need to configure 2 secrets in your GitHub repository.   
 These 2 secrets are `TB_KEY` (your TestingBot Key) and `TB_SECRET` (TestingBot secret) which can be obtained from the TestingBot member area.

In your GitHub repository, go to **Settings** and find the **Secrets** option in the left-hand pane.

Add both the `TB_KEY` and `TB_SECRET` as **Repository Secrets** :

 ![GitHub Secrets](https://testingbot.com/assets/support/github/secrets-5e390bc9c169a9b3e4d247c00606334ada9202d731436d23d7f96c099d0b1829.webp)
## Set up a GitHub workflow

Next, we'll create a new GitHub workflow. Create a workflow file `test-workflow.yml` in the `.github/workflows` directory of your GitHub repository.   
 You can find out more about workflow files on the [GitHub documentation pages](https://docs.github.com/en/actions/learn-github-actions#creating-a-workflow-file).

In your workflow file, you can indicate [when to run the GitHub Action](https://docs.github.com/en/actions/reference/events-that-trigger-workflows).  
We recommend doing this on both `push` and `pull_request` for maximum test coverage:

    name: "TestingBot Test"
    on: [push, pull_request]
    
    jobs:
        test:
            runs-on: ubuntu-latest
            name: Sample Test
    ...

You can specify a `runs-on` parameter, to indicate the OS of the container that should run your test.

The most important part is the `steps` section, which we'll cover in the example below.

## Example workflow with TestingBot

Let's set up a workflow that will do the following actions:

- Checkout the current GitHub repository code
- Install dependencies for the project
- Run the tests in the repository 

    name: "PR Checks"
    on: push
    
    jobs:
        test:
            runs-on: ubuntu-latest
            name: Action Test
            steps:
                - uses: actions/checkout@v4
                - uses: testingbot/testingbot-tunnel-action@v1
                  with:
                    key: ${{ secrets.TB_KEY }}
                    secret: ${{ secrets.TB_SECRET }}
                    tunnelIdentifier: github-action-tunnel
    
                - name: "Install Dependencies"
                  run: npm install
    
                - name: "Run Test"
                  run: npm run test
                  env:
                    TB_KEY: ${{ secrets.TB_KEY }}
                    TB_SECRET: ${{ secrets.TB_SECRET }}

Here we're including the `testingbot/testingbot-tunnel-action` TestingBot GitHub action with a `key`, `secret` and `tunnelIdentifier`.

The `tunnelIdentifier` is used to indicate in your tests that a connection should be made to this specific tunnel.

### Example Test

For example, let's say your `npm run test` starts a local `http-server` and then runs a `Selenium WebDriver` test:

    http-server ./test -p 8080 > /dev/null 2>&1 &

[Ruby](https://testingbot.com#)[Python](https://testingbot.com#)[PHP](https://testingbot.com#)[Java](https://testingbot.com#)[NodeJS](https://testingbot.com#)[C#](https://testingbot.com#)

    #!/usr/bin/env ruby
    
    require 'rubygems'
    require 'selenium-webdriver'
    
    options = Selenium::WebDriver::Chrome::Options.new
    options.add_option('platformName', 'WIN11')
    options.add_option('browserVersion', 'latest')
    options.add_option('tb:options', {
      'key' => ENV['TB_KEY'],
      'secret' => ENV['TB_SECRET'],
      'name' => 'GitHub Action Test',
      'tunnel-identifier' => 'github-action-tunnel'
    })
    
    driver = Selenium::WebDriver.for(
      :remote,
      url: "https://hub.testingbot.com/wd/hub",
      options: options)
    driver.navigate.to "http://localhost:8080"
    puts driver.title
    driver.quit

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    import org.openqa.selenium.remote.RemoteWebDriver;
    
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    public class AccessibilityTest {
    
      public static final String KEY = System.getenv("TB_KEY");
      public static final String SECRET = System.getenv("TB_SECRET");
      public static final String URL = "https://hub.testingbot.com/wd/hub";
    
      public static void main(String[] args) throws Exception {
        ChromeOptions options = new ChromeOptions();
        options.setCapability("browserVersion", "latest");
        options.setCapability("platformName", "WIN11");
    
        Map<String, Object> tbOptions = new HashMap<>();
        tbOptions.put("key", KEY);
        tbOptions.put("secret", SECRET);
        tbOptions.put("name", "GitHub Action Test");
        tbOptions.put("tunnel-identifier", "github-action-tunnel");
        options.setCapability("tb:options", tbOptions);
    
        WebDriver driver = new RemoteWebDriver(new URL(URL), options);
        driver.get("http://localhost:8080");
    
        System.out.println(driver.getTitle());
    
        driver.quit();
      }
    }

    <?php
    
    require_once('vendor/autoload.php');
    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\Remote\DesiredCapabilities;
    
    $tbKey = getenv('TB_KEY');
    $tbSecret = getenv('TB_SECRET');
    
    $capabilities = DesiredCapabilities::chrome();
    $capabilities->setCapability('platformName', 'WIN11');
    $capabilities->setCapability('browserVersion', 'latest');
    $capabilities->setCapability('tb:options', [
      'key' => $tbKey,
      'secret' => $tbSecret,
      'name' => 'GitHub Action Test',
      'tunnel-identifier' => 'github-action-tunnel'
    ]);
    
    $web_driver = RemoteWebDriver::create(
      "https://hub.testingbot.com/wd/hub",
      $capabilities,
      120000
    );
    $web_driver->get("http://localhost:8080");
    echo $web_driver->getTitle();
    $web_driver->quit();
    ?>

    import os
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    options = Options()
    options.set_capability('platformName', 'WIN11')
    options.set_capability('browserVersion', 'latest')
    options.set_capability('tb:options', {
      'key': os.environ['TB_KEY'],
      'secret': os.environ['TB_SECRET'],
      'name': 'GitHub Action Test',
      'tunnel-identifier': 'github-action-tunnel'
    })
    
    driver = webdriver.Remote(
        command_executor='https://hub.testingbot.com/wd/hub',
        options=options
    )
    driver.get("http://localhost:8080")
    print(driver.title)
    driver.quit()

    const webdriver = require('selenium-webdriver');
    const chrome = require('selenium-webdriver/chrome');
    
    const testingbotKey = process.env.TB_KEY;
    const testingbotSecret = process.env.TB_SECRET;
    
    async function runGitHubActionTest () {
      let options = new chrome.Options();
      options.set('platformName', 'WIN11');
      options.set('browserVersion', 'latest');
      options.set('tb:options', {
        'key': testingbotKey,
        'secret': testingbotSecret,
        'name': 'GitHub Action Test',
        'tunnel-identifier': 'github-action-tunnel'
      });
    
      let driver = new webdriver.Builder()
        .usingServer('https://hub.testingbot.com/wd/hub')
        .withCapabilities(options)
        .build();
      await driver.get("http://localhost:8080");
      const title = await driver.getTitle();
      console.log(title);
      await driver.quit();
    }
    runGitHubActionTest();

    using System;
    using System.Collections.Generic;
    using OpenQA.Selenium;
    using OpenQA.Selenium.Chrome;
    using OpenQA.Selenium.Remote;
    
    namespace SeleniumTest {
      class Program {
        static void Main(string[] args) {
          var options = new ChromeOptions();
          options.PlatformName = "WIN11";
          options.BrowserVersion = "latest";
          options.AddAdditionalOption("tb:options", new Dictionary<string, object>
          {
            { "key", Environment.GetEnvironmentVariable("TB_KEY") },
            { "secret", Environment.GetEnvironmentVariable("TB_SECRET") },
            { "name", "GitHub Action Test" },
            { "tunnel-identifier", "github-action-tunnel" }
          });
    
          IWebDriver driver = new RemoteWebDriver(
            new Uri("https://hub.testingbot.com/wd/hub"), options
          );
          driver.Navigate().GoToUrl("http://localhost:8080");
          Console.WriteLine(driver.Title);
          driver.Quit();
        }
      }
    }

Your test will connect to the local http-server via the TestingBot GitHub Action and print the title of the page.

## Inputs

The TestingBot GitHub Action accepts the following inputs:

| Input | Description |
| --- | --- |
| `key`  
**Required** | Your TestingBot API Key |
| `secret`  
**Required** | Your TestingBot API Secret |
| `auth` | Performs Basic Authentication for specific hosts, only works with HTTP. |
| `debug` | Enables debug messages. Will output request/response headers. |
| `dns` | Use a custom DNS server. For example: 8.8.8.8 |
| `doctor` | Perform sanity/health checks to detect possible misconfiguration or problems. |
| `fastFailRegexps` | Specify domains you don't want to proxy, comma separated. |
| `pac` | Proxy autoconfiguration. Should be a http(s) URL |
| `sePort` | The local port your Selenium test should connect to. Default port is 4445 |
| `localProxy` | The port to launch the local proxy on (default 8087). |
| `proxy` | Specify an upstream proxy: `PROXYHOST:PROXYPORT` |
| `proxyCredentials` | Username and password required to access the proxy configured with `proxy`. |
| `noCache` | Bypass TestingBot Caching Proxy running on the tunnel VM. |
| `noProxy` | Do not start a local proxy (requires user provided proxy server on port 8087). |
| `tunnelIdentifier` | Add an identifier to this tunnel connection.  
 In case of multiple tunnels, specify this identifier in your desired capabilities to use this specific tunnel. |
| `uploadLogFile` | Should this action [upload the log file](https://testingbot.com#artifacts) generated by the TestingBot Tunnel as an artifact?   
Default is true. |
| `retryTimeout` | How long, in seconds, should the Action wait to retry, if the tunnel fails to start. |

## Artifacts

The TestingBot GitHub Action will, by default, upload the logfile generated by the TestingBot tunnel.   
 This allows you to view what happened with the TestingBot Tunnel for each of your Actions.   
 The logfile is saved as an artifact and can be downloaded.

 ![GitHub Artifact](https://testingbot.com/assets/support/github/artifact-9ec2869f7e562823c0fac8784cbde1a2fc0820830e31410393405b00bed32d49.webp)

If you don't want this, you can disable it by setting the input `uploadLogFile: "false"` in your workflow file.

## More Information

More information about this is available on the [GitHub Documentation pages](https://docs.github.com/en/actions) and our [TestingBot GitHub Action repository](https://github.com/testingbot/testingbot-tunnel-action).

Was this page helpful? Yes No 

## Looking for More Help?

Have questions or need more information?   
 You can reach us via the following channels:

- [Email us](https://testingbot.com/contact/new)
- [Join our Slack Channel](https://join.slack.com/t/testingb0t/shared_invite/zt-3bcw9xch-jk19~6XPs_xBrsAgAedkCw)
