Headless mode 编辑
Headless mode is a very useful way to run Firefox. Just as it might sound, Firefox is run as normal, minus any visible UI components visible. Though not so useful for surfing the web, it comes into its own with automated testing. This article provides all you need to know about running headless Firefox.
Using headless mode
This section provides usage instructions for headless mode.
Basic usage
You can run Firefox in headless mode from the command line, by including the -headless
flag. For example:
/path/to/firefox -headless
You need to run your headless Firefox with a new profile, otherwise you'll run into an error because you can't have two instances open with the same profile.
To create a new profile, go to the about:profiles
page in Firefox and use the Create a New Profile button.
Once created, you can specify running firefox with the new profile usig the -P
flag followed by the name of the profile:
/path/to/firefox -P my-profile -headless
Taking screenshots
Since Firefox 57, the --screenshot
flag allows you to take screenshots of websites. The basic usage is as follows:
/path/to/firefox -P my-profile -headless --screenshot /wiki/
This creates a full-height screenshot of https://www.wenjiangs.com/wp-content/uploads/2020/mozilla/code called codescreenshot.
, in the active directory, with a viewport width of 800px.
You can omit -headless
when using --screenshot
, as it is implied:
/path/to/firefox -P my-profile --screenshot /wiki/
To override the default values, mentioned above, you can use the following flags/features:
--screenshot name url
— Set a custom name for the screenshot by including it between the--screenshot
flag and the URL you want to capture. You can specify other web-compatible image formats such as.jpg
,.bmp
, etc.--window-size=x
— Set a custom viewport width when taking the screenshot (full height is maintained). Note that the single argument version of this doesn't work.--window-size=x,y
— Set a custom viewport width and height to capture.
For example, the following command creates a screenshot of https://developer.mozilla.com
, in the active directory called test.jpg
, with a viewport width of 800px, and a height of 1000px:
/path/to/firefox -P my-profile --screenshot test.jpg https://developer.mozilla.org --window-size=800,1000
Note: There is a bug whereby taking a screenshot can sometimes fail if the specified URL is redirected (see Headless doesn't work when redirect is involved). Make sure you specify the final URL that you want to screenshot.
Automated testing with headless mode
The most useful way to use headless Firefox, is to run automated tests. You can make your testing process much more efficient.
Selenium in Node.js
Here we'll create a Selenium test, using Node.js and the selenium-webdriver
package. For this guide, we'll assume that you already have basic familiarity with Selenium, Webdriver, and Node, and you already have a testing environment created. If not, work through our Setting up Selenium in Node guide, and return when you have.
First, confirm you've installed Node and the selenium-webdriver
on your system. Then create a new file, called selenium-test.js,
and follow the steps below to populate it with test code.
Note: Alternatively, you could clone our headless-examples repo. This also includes a package file, so you can just use npm install
to install necessary dependencies.
Let's add some code. Inside this file, start by importing the main
selenium-webdriver
module, and thefirefox
submodule:var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until; var firefox = require('selenium-webdriver/firefox');
Next, we create a new
options
object, and add the-headless
argument to tell the driver instance we create below to run in headless mode:var options = new firefox.Options(); options.addArguments("-headless");
Now let's create a new driver instance for Firefox, using setFirefoxOptions()
to include our options
object:
var driver = new webdriver.Builder() .forBrowser('firefox') .setFirefoxOptions(options) .build();
Alternatively, you can use options to set the binary and the headless arguments:
var firefoxOptions = new firefox.Options(); firefoxOptions.setBinary('/path/to/binary'); firefoxOptions.headless(); const driver = new webdriver.Builder() .forBrowser('firefox') .setFirefoxOptions(firefoxOptions) .build();
Finally, add the following code, which performs a simple test on the Google search homepage:
driver.get('https://www.google.com'); driver.findElement(By.name('q')).sendKeys('webdriver'); driver.sleep(1000).then(function() { driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB); }); driver.findElement(By.name('btnK')).click(); driver.sleep(2000).then(function() { driver.getTitle().then(function(title) { if(title === 'webdriver - Google Search') { console.log('Test passed'); } else { console.log('Test failed'); } }); }); driver.quit();
Finally, run your test with following command:
node selenium-test
That's it! After a few seconds, you should see the message "Test passed" returned in the console.
Headless Firefox in Node.js with selenium-webdriver, by Myk Melez, contains additional useful tips and tricks for running Node.js Selenium tests with headless mode.
Selenium in Java
Note: Thanks a lot to nicholasdipiazza for writing these instructions!
This guide assumes you already have Geckodriver on your machine, as explained in Setting up Selenium in Node, and an IDE set up which supports Gradle projects.
Download our headlessfirefox-gradle.zip archive (see the source here). Extract it, and import the headlessfirefox folder into your IDE, as a gradle project.
Edit the
build.gradle
file, to set selenium to a later version, if needed. At the time of writing, we used 3.5.3.group 'com.mozilla' version '1.0' apply plugin: 'java' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile('org.seleniumhq.selenium:selenium-api:3.5.3') compile('org.seleniumhq.selenium:selenium-remote-driver:3.5.3') compile('org.seleniumhq.selenium:selenium-server:3.5.3') testCompile group: 'junit', name: 'junit', version: '4.12' }
Edit the
webdriver.gecko.driver
property, in the HeadlessFirefoxSeleniumExample.java file, to equal the path where you installed geckodriver (see line 15 below).package com.mozilla.example; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxBinary; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; import java.util.concurrent.TimeUnit; public class HeadlessFirefoxSeleniumExample { public static void main(String [] args) { FirefoxBinary firefoxBinary = new FirefoxBinary(); firefoxBinary.addCommandLineOptions("--headless"); System.setProperty("webdriver.gecko.driver", "/opt/geckodriver"); FirefoxOptions firefoxOptions = new FirefoxOptions(); firefoxOptions.setBinary(firefoxBinary); FirefoxDriver driver = new FirefoxDriver(firefoxOptions); try { driver.get("http://www.google.com"); driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS); WebElement queryBox = driver.findElement(By.name("q")); queryBox.sendKeys("headless firefox"); WebElement searchBtn = driver.findElement(By.name("btnK")); searchBtn.click(); WebElement iresDiv = driver.findElement(By.id("ires")); iresDiv.findElements(By.tagName("a")).get(0).click(); System.out.println(driver.getPageSource()); } finally { driver.quit(); } } }
Run the java class, and you should see the HTML content of this page printed in your console/terminal.
Selenium in Python
This guide assumes you already have geckodriver on your machine, as explained in Setting up Selenium in Node.
Install the latest version of the Python client for Selenium.
Edit the following, to set the
executable_path
on line 11, to the path where you installed geckodriver:from selenium.webdriver import Firefox from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.firefox.options import Options from selenium.webdriver.support import expected_conditions as expected from selenium.webdriver.support.wait import WebDriverWait if __name__ == "__main__": options = Options() options.add_argument('-headless') driver = Firefox(executable_path='geckodriver', options=options) wait = WebDriverWait(driver, timeout=10) driver.get('http://www.google.com') wait.until(expected.visibility_of_element_located((By.NAME, 'q'))).send_keys('headless firefox' + Keys.ENTER) wait.until(expected.visibility_of_element_located((By.CSS_SELECTOR, '#ires a'))).click() print(driver.page_source) driver.quit()
Run the Python script, and you should see the HTML content of this page printed in your console/terminal.
Debugging headless Firefox
You need to set a few preferences to allow remote debugging:
{
"moz:firefoxOptions": {
args: ["-headless"],
prefs: {
"devtools.debugger.remote-enabled": true,
"devtools.debugger.prompt-connection": false,
"devtools.chrome.enabled": true
}
}
}
The example above shows the capabilities block required for WebdriverIO, other tools would require the same configuration. Then you will need to follow the remote debugging instructions.
Troubleshooting and further help
If you are having trouble getting headless mode to work, then do not worry — we are here to help. This section is designed to be added to as more questions arise, and answers are found.
- On Linux, certain libraries are currently required on your system, even though headless mode doesn't use them, as Firefox links against them. See bug 1372998, for more details and progress towards a fix.
If you want to ask the engineers a question, the best place to go is the #headless
channel on Mozilla IRC. If you are pretty sure you've found a bug, file it on Mozilla Bugzilla.
See also
- Using Selenium with Headless Firefox (on Windows) by Andre Perunicic (uses Python)
- Headless Firefox in Node.js with selenium-webdriver by Myk Melez
- Using Selenium with Headless Firefox on Travis-CI by Josef Rousek
- TestCafe (v.0.18.0 and higher) also supports testing in headless Firefox, by default. See the documentation for the details.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论