MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/d6d7ff2e2f9c

Headless mode는 Firefox를 실행시키기 위한 유용한 방법입니다, 즉 UI컴포넌트가 보이지 않더라도 Firefox는 정상적으로 움직인다는 것입니다. 웹서핑하기에는 불편할 지라도 테스트를 자동화하기에는 매우 유용합니다. 이 글은 Headless Firefox 실행을 위해 알아야할 모든 것을 제공합니다.

headless mode를 사용하기

-headless flag를 붙이는 것만으로 코맨드라인에서 headless mode를 실행할 수 있습니다.

/path/to/firefox -headless

지금은 심플하게 되어있습니다만 앞으로 옵션을 추가할 예정입니다. 

하나의 예를 들자면, headless Firefox를 이용해서 간단하게 스크린샷을 찍을 수 있는 -screenshot 옵션을 작업하고 있습니다.  현재 진행사항은 여기서 bug 1378010 볼 수 있습니다.

Browser support

Headless Firefox는 리눅스에서는 Firefox55이상, 윈도우즈와 맥에서는 Firefox56이상의 버전에서 지원하고 있습니다.

headless mode를 이용한 테스트 자동화

headless Firefox를 이용하는 가장 유용한 방법은 자동화된 테스트와 함께 이용하는 것입니다. 즉,테스트의 과정을 더욱 더 효율적으로 만들어 낼 수 있다는 것입니다. 

Selenium in Node.js

여기서는 Node.js 와 selenium-webdriver 패키지를 이용해서 Selenium테스트를 만들어 볼 것입니다. 이 가이드는 Selenium, Webdriver 그리고 Node에 대한 기본적인 지식과 테스팅 환경 설정이 완료되어 있다는 가정하에 쓰여져 있습니다. 그렇지 않다면 Setting up Selenium in Node 를 먼저 보시고 난 후에 본 가이드를 이용하실 것을 권장합니다.

먼저 Node와 selenium-webdriver패키지가 설치되어 있는지 확인합니다. 그리고 selenium-test.js라는 파일을 만들어서 불러옵니다. 그런 후 아래의 내용을 단계별로 진행합니다.

Note: 다른 방법으로는 headless-examples repo;가 이용 가능합니다.
npm install을 이용하는 것만으로 필요한 라이브러리를 설치해 포함시킬수 있습니다.

  1. selenium-webdriver module과 firefox submodule을 불러오는 로직을 추가합니다.

    var webdriver = require('selenium-webdriver'),
        By = webdriver.By,
        until = webdriver.until;
    
    var firefox = require('selenium-webdriver/firefox');
  2. 다음으로, Firefox Nightly를 설정한 binary objecet를 작성합니다. 그리고 argument를 -headless로 해서 추가하면 headless mode를 실행시키기 위한 준비가 완료됩니다. 

    var binary = new firefox.Binary(firefox.Channel.NIGHTLY);
    binary.addArguments("-headless");
  3. Firefox용으로 웹드라이버 인스탄스를 작성합니다. 그리고 setFirefoxOptions() 를 이용해서 작성해둔 바이너리를 설정합니다. ( 이 작업은 리눅스와 윈도우즈와 맥에서 headless mode가 릴리즈 되면 불필요합니다. 하지만 Nightly-specific feature에서 테스트하기를 원한다면 유용합니다 )

    var driver = new webdriver.Builder()
        .forBrowser('firefox')
        .setFirefoxOptions(new firefox.Options().setBinary(binary))
        .build();
  4. 구글 검색페이지를 이용하는 간단한 테스트를 수행하는 코드를 추가합니다.

    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();
  5. 마지막으로 아래의 명령어와 함께 테스트를 실행해주세요.

    node selenium-test

몇 초 후 콘솔에서 "Test passed"를 보게될 겁니다.  이게 다입니다! 

headless mode를 이용한 Node.js Selenium tests에 관한 유용한 팁이나 트릭은 이 글 (Headless Firefox in Node.js with selenium-webdriver by Myk Melez) 을 참고해주세요.

Selenium in Java

Note: Thanks a lot to nicholasdipiazza for writing these instructions!

 Gradle projects를 지원하는 IDE를 사용하고 있고 Setting up Selenium in Node 가이드에 설명되어진대로 Geckodriver가 설치되어져 있다는 가정하에 쓰여져 있습니다.

  1. headlessfirefox-gradle.zip 를 다운로드합니다. (see the source here), 압축을 풉니다, 그리고 headlessfirefox폴더를 IED에 gradle project로 Import합니다.

  2. build.gradle파일에 selenium을 설정합니다. 필요에 따라 다른 버전을 이용하셔도 상관없습니다. 이번 글에서는 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'
    }
  3. geckodriver를 설치한 경로와 같은 곳에 있는 HeadlessFirefoxSeleniumExample.java 파일에서 webdriver.gecko.driver property를 수정합니다. (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();
       }
     }
    }
  4. 자바 클래스를 실행시킵니다. 그러면 컨솔 또는 터미널에 출력된 HTML컨텐츠를 확인할 수 있습니다.

(headless Firefox를 지원하는) 다른 테스팅 솔루션

Slimerjs는 리눅스에서 Firefox를 지원합니다. 윈도우즈와 맥은 지원 예정입니다. 상세한 내용은 이 글 ( Headless SlimerJS with Firefox by Brendan Dahl) 을 참고해주세요.

그 외에 환경변수가 설정가능하다면 거의 모든 일반적인 테스팅 어플리케이션에서 쓰여진 자동화된 테스트에서 headless Firefox를 이용할 수 있습니다. 

트러블슈팅과 상세 지원에 관해

headless mode를 이용중에 문제가 발생했을 경우에는 걱정하시지 말고 이 섹션을 찾아주세요.  이 섹션은 질문이 더 생기거나 답을 찾았을 경우에 내용을 추가 할 수 있도록 설계되어있습니다.

  • 현재 리눅스에서 사용하고 있는 시스템 안에서 headless mode가 쓰이지 않더라도  특정 라이브러리를 필요로 합니다. — 왜냐하면 Firefox에서 사용하고 있기 때문입니다. 상세한 내용과 진행상황은 여기를 bug 1372998 참고해주세요.

엔지니어에게 질문이 있다면 Mozilla IRC#headless 채널이 최고의 장소입니다. 그리고 버그를 확실하게 발견하셨다면 Mozilla Bugzilla에서 내용을 알려주세요. 

관련 글

문서 태그 및 공헌자

 이 페이지의 공헌자: daebum-lee, hagyung999
 최종 변경: daebum-lee,