見出し画像

Dockerで起動しているブラウザのファイル項目を入力する方法


はじめに

こんにちは。SHIFTのテスト自動化エンジニアの松岡です。
Selenideは、Javaで記述できるweb画面の自動テストツールです。
CI/CDなどで利用する際、Dockerを使用してサーバ上にdocker-seleniumのコンテナプロセスを常駐させておくと、サーバに直接ブラウザをインストールすることなく、ヘッドレスブラウザの自動テスト実行環境を構築することができます。(今回環境構築の説明は割愛) これにより、Javaの自動テストスクリプトからはDockerコンテナで設定したlocalhostのポート番号に接続するだけで、ブラウザ操作が出来るようになりますが、ファイルの入力項目に関しては、Selenideではなく、元となるSeleniumでアクセスする必要があります。 今回、ブラウザはDockerコンテナを使用している場合のファイル入力項目の操作方法について、解説していきます。

◆想定されるケース

  • 開発者のローカルマシンではなく、サーバ上でweb画面のテスト自動化をしたい。

  • サーバにはChromeインストールしたくない。または、すでにインストール済みのChromeとは別のバージョンでテスト実行したい。(そのためDocker上でブザウザを使用する)

  • 実行されるテストケースには画面入力項目がある

◆前提条件

  • 使用するサーバはLinux

  • Dockerが自動テストを実行するサーバにインストールされていること。

  • サーバにて、Standalone-chromeのコンテナプロセスが立ち上がっていること。

  • テストスクリプトで使用するブラウザはサーバ上のコンテナプロセスを使用するように設定されていること。

  • 入力に使用するファイルは、テストスクリプトからアクセス可能なローカルファイルであること。(resourceに用意するか、テストシナリオ内でファイルを生成する)

◆全体構成図

  • 今回のテストのシステム構成は以下の通りです。

◆各種クラスファイル一覧

  • テスト用クラス

    • BaseTest……テストシナリオのスーパークラス

    • FooTest……実際のテストシナリオ。BaseTestを継承

  • ページオブジェクト

    • BasePage……ページオブジェクトのスーパークラス

    • TestPage……ファイル入力項目が存在するページオブジェクト。BasePageを継承

以下に、各クラスの記載内容を説明していきます。(※packageおよびimport の記述は割愛)

【1】BaseTest.java

public class BaseTest{
   public static WebDriver driver;

   @BeforeAll
   public static void createDriver() {
      ChromeOptions options = new ChromeOptions();
      options.setCapability("browserVersion", "foo"); //テストで必要なchromeのバージョンを記載する
      options.addArguments("--headless"); //headlessで実行
      Dimension targetSize = new Dimension(1280, 720); //ブラウザのサイズ

      try {
            URL url = new URL("http://localhost:1234/wd/hub"); // Dockerで設定したポート番号

            driver = new RemoteWebDriver(url, options);
            driver.manage().window().setSize(targetSize); //ウィンドウサイズ
            WebDriverRunner.setWebDriver(driver);
      } catch (Exception e) {
            // 例外発生時の処理(※記述を省略)
      }
   }

   // driverの終了処理
   @AfterAll
   public static void quit(){
      if (driver != null) {
            driver.quit();
      }
   }

}

Docker上のブラウザにアクセスして操作する場合の一例です。
【2】FooTest.java

@Feature("ファイル操作を含むシナリオ")
public class FooTest extends BaseTest{

   public static final String sutURL = "foobar"; //テスト対象のURL
   
   @Test
   @Description("ファイル項目操作")
   public void testFileInput() {
      open(sutURL);
      TestPage testPage = new TestPage();
      testPage.inputFileXXX("filePath") // ファイル項目入力の操作メソッド呼び出し
      …(以下後続シナリオ省略)…
      ;
   }
}

テストシナリオのクラスです。 testPageのinputFileXXXメソッドを呼び出し、ファイル項目を入力します。引数はファイルパスの文字列となります。

【3】TestPage.java

public class TestPage extends BasePage {
   public TestPage(){
      // ※コンストラクタによるページ遷移時のアサーション処理(記載を省略)
   }

   // ファイル入力項目のセレクター
   private SelenideElement fileInputElement = $("#hogehoge");

   @Step("ファイル項目を入力")
   public TestPage inputFileXXX(String filePath) {
      fileInputElement.should(exist);
      inputFileElement(fileInputElement, filePath);
      return this;
   }
}

テスト対象となるファイル入力項目が存在する画面のページオブジェクトです。 FooTestクラスから呼び出されるinputFileXXXメソッドがあります。 入力項目の存在確認(exist)をしてから、スーパークラス(BasePage)のinputFileElementメソッドを呼び出します。

【4】BasePage.java

public class BasePage {
   protected void inputFileElement(SelenideElement fileElement, String filePath) {
      // ローカルファイルパスをFile型に変換
      LocalFileDetector lfd = new LocalFileDetector();
      File localFile = lfd.getLocalFile(filePath);
      // absolutePathを取得
      String absoluteFilePath = localFile.getAbsolutePath();

      // ファイルインプット処理
      WebElement fileInputWebElement = fileElement.toWebElement();
      ((RemoteWebElement) fileInputWebElement).setFileDetector(lfd);

      fileInputWebElement.sendKeys(absoluteFilePath);
   }
}

TestPageのスーパークラスです。
inputFileElementメソッドの第1引数の段階ではSelenideElement型ですが、toWebElementメソッドでWebElement型に変換した後、更にRemoteWebElement型にキャストしています。
こうすることで、今回のDockerプロセスのようなリモートWebDriverでローカルファイルのabsolutePathを sendKeysメソッドで(SelenideではなくSeleniumの処理として)セットすることができるようになります。

※ エディタの都合上インデントがずれてしまう場合があります。コピペ時にお手元でご確認ください。


執筆者プロフィール:松岡 直人
SIerでのJava、jqueryの開発経験を経て、SHIFTに入社。 SHIFTでは入社当初より画面/APIテスト自動化に関わる。 「人間が最低限しか頑張らない自動化」を目指している。

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら   
https://recruit.shiftinc.jp/career/

UnsplashPietro Jeng