How to change the language of a WebDriver?

2019-01-22 12:54发布

I want to execute my Selenium tests in different languages. Is it possible to change the language of an existing WebDriver at runtime or do I have to recreate the browser instance?

Right now I'm only using Firefox, but I want to execute tests in different browsers at some later point.

In Firefox I set the language like this:

FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("intl.accept_languages", "de");
WebDriver driver = new FirefoxDriver(profile);

I also implemented a WebDriverPool, which holds a WebDriver instance so it can be shared among tests. If the language can only be set at creation time, I could hold an instance for every locale.

All in all I wonder if I miss something here. Why is it so hard to change the language? shouldn't there be a method like WebDriver.setAcceptLanguages(Locale)?

In a nutshell I have these questions:

  1. Why isn't there WebDriver.setAcceptLanguages(Locale)?
  2. How to change the language for the dirrerent WebDrivers?
  3. Can I change the language at runtime?
  4. How did you guys implement your WebDriverPool or do you recreate them everytime?

3条回答
兄弟一词,经得起流年.
2楼-- · 2019-01-22 13:27

You can also do it through about:config in firefox. But you need to use Actions to manipulate it.

Below a java piece of code

    Actions act = new Actions(webDriver);          

    webDriver.get("about:config");

    // warning screen
    act.sendKeys(Keys.RETURN).perform();

    // Go directly to the list, don't use the search option, it's not fast enough
    act.sendKeys(Keys.TAB).perform();

    // Go to the intl.accept_languages option
    act.sendKeys("intl.accept_languages").sendKeys(Keys.RETURN).perform();

    // fill the alert with your parameters
    webDriver.switchTo().alert().sendKeys("fr, fr-fr, en-us, en");
    webDriver.switchTo().alert().accept();
查看更多
我命由我不由天
3楼-- · 2019-01-22 13:49

I ended up creating a WebDriverPool that creates one instance for every combination of WebDriver type (e.g. FirefoxDriver.class) and Locale (e.g. en_US). Maybe this is usful for someone.

public class WebDriverPool {

  private Map<String, WebDriver> drivers = new HashMap<String, WebDriver>();
  private List<WebDriver> driversInUse = new ArrayList<WebDriver>();

  public WebDriverPool() {
    Runtime.getRuntime().addShutdownHook(new Thread(){
      @Override
      public void run(){
        for (WebDriver driver : drivers.values())
          driver.close();

        if (!driversInUse.isEmpty())
          throw new IllegalStateException("There are still drivers in use, did someone forget to return it? (size: " + driversInUse.size() + ")");
      }
    });
  }

  private WebDriver createFirefoxDriver(Locale locale){
    FirefoxProfile profile = new FirefoxProfile();
    profile.setPreference("intl.accept_languages", formatLocale(locale));
    return new FirefoxDriver(profile);
  }

  private String formatLocale(Locale locale) {
    return locale.getCountry().length() == 0
      ? locale.getLanguage()
      : locale.getLanguage() + "-" + locale.getCountry().toLowerCase();
  }

  /**
   * @param clazz
   * @param locale
   * @return web driver which can be new or recycled
   */
  public synchronized WebDriver getWebDriver(Class<? extends WebDriver> clazz, Locale locale){

    String key = clazz.getName() + "-" + locale;

    if(!drivers.containsKey(key)){

      if(clazz == FirefoxDriver.class){
        drivers.put(key, createFirefoxDriver(locale));
      }

      // TODO create other drivers here ...

      // else if(clazz == ChromeDriver.class){
      //     drivers.put(key, createChromeDriver(locale));
      // }

      else{
        throw new IllegalArgumentException(clazz.getName() + " not supported yet!");
      }
    }

    WebDriver driver = drivers.get(key);

    if(driversInUse.contains(driver))
      throw new IllegalStateException("This driver is already in use. Did someone forgot to return it?");

    driversInUse.add(driver);
    return driver;
  }

  public synchronized void returnWebDriver(WebDriver driver){
    driversInUse.remove(driver);
  }
}
查看更多
Evening l夕情丶
4楼-- · 2019-01-22 13:50

I am afraid that the whole idea of WebDriver is to act like browser - so you can change the language of the browser, but you have to change the locale in the Operating system, or hope that the application will do it for you.

For instance - German number format separates decimal number by comma and English one by dot. If you want to test, how the number format behaves in English locale and in German locale, you can do it only by these two approaches:

  1. Change OS locale from German to English or vice versa
  2. Change browser language and hope that application will change the behavior.

To answer your questions:

  1. There is no setLocale on Webdriver, because WebDriver simulates browser, not OS
  2. I would do it like this (Java code):

    private WebDriver driver;  
    
    public enum Language {en-us, de}
    
    public WebDriver getDriver(Language lang){
      String locale = lang.toString();
      FirefoxProfile profile = new FirefoxProfile();
      profile.setPreference("intl.accept_languages", locale);
      driver = new FirefoxDriver(profile);   
      return driver;       
    }
    
    @Test
    public void TestNumber(){
      WebDriver drv = getDriver(Language.en);
      drv.get("http://the-site.com");
      WebElement el = drv.findElement //... find element
      String number = el.getText();
      Assert.assertEquals(number, "123.45");
      drv.close();
      drv = getDriver(Language.de);
      drv.get("http://the-site.com");
      WebElement el = drv.findElement //... find element
      String number = el.getText();
      Assert.assertEquals(number, "123,45");
      drv.close();
    }
    
  3. I am afraid you have to close the browser and open it again with different language.

  4. I personally create new instance of the browser for each test.

BTW the above bit of code assumes, that the web application changes the way how to show numbers to the user based on browser language.

查看更多
登录 后发表回答