Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Passing Command Line Arguments To Driver #198

Open
oomelianchuk opened this issue Aug 3, 2021 · 1 comment · May be fixed by #201
Open

Support Passing Command Line Arguments To Driver #198

oomelianchuk opened this issue Aug 3, 2021 · 1 comment · May be fixed by #201
Assignees

Comments

@oomelianchuk
Copy link
Contributor

All the currently supported webdrivers accept their own list of arguments, which allow to customize the behavior of the driver itself. It might be useful e.g. to decrease the logging level of the driver.

From the list of avaliable option for chromedriver:

Options
  --port=PORT                     port to listen on
  --adb-port=PORT                 adb server port
  --log-path=FILE                 write server log to file instead of stderr, increases log level to INFO
  --log-level=LEVEL               set log level: ALL, DEBUG, INFO, WARNING, SEVERE, OFF
  --verbose                       log verbosely (equivalent to --log-level=ALL)
  --silent                        log nothing (equivalent to --log-level=OFF)
  --append-log                    append log file instead of rewriting
  --replayable                    (experimental) log verbosely and don't truncate long strings so that the log can be replayed.
  --version                       print the version number and exit
  --url-base                      base URL path prefix for commands, e.g. wd/url
  --readable-timestamp            add readable timestamps to log
  --enable-chrome-logs            show logs from the browser (overrides other logging options)
  --disable-dev-shm-usage         do not use /dev/shm (add this switch if seeing errors related to shared memory)
  --allowed-ips                   comma-separated allowlist of remote IP addresses which are allowed to connect to ChromeDriver

and from geckodriver:

USAGE:
    geckodriver [FLAGS] [OPTIONS]

FLAGS:
        --connect-existing    Connect to an existing Firefox instance
    -h, --help                Prints this message
        --jsdebugger          Attach browser toolbox debugger for Firefox
    -v                        Log level verbosity (-v for debug and -vv for trace level)
    -V, --version             Prints version and copying information

OPTIONS:
        --android-storage <ANDROID_STORAGE>    Selects storage location to be used for test data (deprecated). [possible values: auto, app, internal, sdcard]
    -b, --binary <BINARY>                      Path to the Firefox binary
        --log <LEVEL>                          Set Gecko log level [possible values: fatal, error, warn, info, config, debug, trace]
        --marionette-host <HOST>               Host to use to connect to Gecko [default: 127.0.0.1]
        --marionette-port <PORT>               Port to use to connect to Gecko [default: system-allocated port]
        --host <HOST>                          Host IP to use for WebDriver server [default: 127.0.0.1]
    -p, --port <PORT>                          Port to use for WebDriver server [default: 4444]

we can see some further use cases of these arguments.

Therefore, it would be nice to help the users passing the arguments to the executable file.

@oomelianchuk
Copy link
Contributor Author

For now, I found only 2 options to enable full support of all driver arguments.

  1. Code approach
    Selenium offers an implementation of DriverService of each webdriver type. The instance of this object can be passed on the creation of webdriver (e.g. new ChromeDriver(driverServer, options)). From this object the webdriver takes the arguments, that should be propagated to the executable file.

The difficulty in this approach is though, that the builders of the DriverServer implementation only offer a limited number of methods for public access. This fact can be overwhelmed with inheritance like in the example below:

import java.io.File;
import java.io.IOException;
import java.util.List;

import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeDriverService.Builder;
import org.openqa.selenium.net.PortProber;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

public class ChromeBuilder extends Builder
{
    private File binary;

    private int port;

    private List<String> arguments;

    public ChromeDriverService createDriverService(List<String> arguments)
    {
        binary = findDefaultExecutable();
        port = PortProber.findFreePort();
        this.arguments = arguments;
        try
        {
            return new ChromeDriverService(binary, port, createArgs(), ImmutableMap.copyOf(System.getenv()));
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected ImmutableList<String> createArgs()
    {
        ImmutableList.Builder<String> argsBuilder = ImmutableList.builder();
        argsBuilder.addAll(super.createArgs());
        argsBuilder.add(String.format("--port=%d", port));
        if (firefoxBinary != null)
        {
            argsBuilder.add("-b");
            argsBuilder.add(binary.getPath());
        } 
        if (arguments != null)
        {
            argsBuilder.addAll(arguments);
        }
        return argsBuilder.build();
    }
}

The wrapper-builder from above can then be used to pass arguments to the driver constructor:

                ChromeDriverService driverServer = new ChromeBuilder().createDriverService(List.of("--log-level=OFF"));

                if (driverServer != null)
                {
                    wDSC.setWebDriver(new ChromeDriver(driverServer, options));
                }
                else
                {
                    wDSC.setWebDriver(new ChromeDriver(options));
                }
  1. Script approach
    Another way to support webdriver arguments is to create a shell script, with the required command, e.g.
#!/bin/sh

chromedriver --log-level=OFF $@

and then use this script as executable.

IMO, the code approach is the more preferred one, as this guarantees platform independence. However, if this approach seems to be "hacky" and hard to maintain, we can select the script approach, as it seems to require lower maintenance effort.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant