見出し画像

【単純反復作業による人的ミスを無くそう!】Seleniumでブラウザ操作を自動化してみる #コード実行編

こんにちは。アバナードの井関です。
前回の#環境セットアップ編に引き続き、後編となるコード実行までの手順をご紹介します。
この記事からご覧になった方はまず#環境セットアップ編に目を通して頂ければと思います。

SeleniumAPIの利用

前回の最後に環境セットアップ後の確認として下記のコードを実行しました。

package TestSelenium;

public class AppTest {
	public static void main(String[] arg) {
		// ChromeDriverのパスを指定
		System.setProperty("webdriver.chrome.driver", "C:\\chromedriver_win32\\chromedriver.exe");

		// ChromeDriverのインスタンス作成(Chrome起動)
		WebDriver driver = new ChromeDriver();

		// 指定したURLに遷移する
		driver.get("https://note.com/avakansai/");
	}
}

ここまでではまだブラウザ画面が開くだけなので、テスト自動化までを考えると他にもSeleniumのAPIのメソッドを組み合わせていく必要があります。

どんなメソッドがあるのか?どんな操作ができるのか?といったことを確認するための便利なサイトとして、Seleniumのクイックリファレンスに逆引き一覧が用意されています。こちらとても重宝します。
Selenium API(逆引き)・・・Selenium APIを利用目的から検索できます

ブラウザ画面の最大化

一例としてブラウザ画面の最大化を実行します。今の状態のサンプルコードではブラウザが起動した際、最大化はされておらずデフォルトサイズのはずです。

画像1

コードの最後に下記を追加し、実行します。

//カレントウインドウを最大化する
driver.manage().window().maximize();

起動したブラウザ画面が最大化されるという動きが確認できました!

画像2

他にも様々なメソッドが用意されていますが、テスト自動化という観点でよく利用されそうなのがHTMLのDOM要素取得です。いくつかの活用例を挙げてみます。

活用例①要素を取得⇒ブラウザ操作

Class名の指定によりテキストボックス要素をオブジェクトして取得し、『指定文字列を入力⇒Enterキー入力』という操作の実行まで行うことができます。

   //検索テキストボックスの要素をClass属性名から取得
   WebElement element = driver.findElement(By.className("gsfi"));
   //検索テキストボックスに"Selenium"を入力
   element.sendKeys("Selenium");
   //Enterキーを押下して検索を実行
   element.sendKeys(Keys.ENTER);

入力するテキストのテストパターンをコードで定義しておき、複数画面に対して同様のパターンでテストすることや、同じ画面の仕様変更の際のデグレテストをすぐに行えるといった利点があります。

活用例②要素の表示テキストを取得⇒期待値と比較

次は要素に設定されている各値の取得です。

   //当ブログトップページのブログ説明文div要素をClass属性名から取得
   WebElement element = driver.findElement(By.className("m-profileBiography"));
   //要素のinnerTextを取得
   System.out.println(element.getText());

一例として当ブログトップページのブログ説明文div要素に設定されたinnerTextを取得します。活用例①と組み合わせて、テキストボックスへの入力後、エラーメッセージに表示されるテキストを取得できます。
期待値を定義しておけば合否判定まで行うことができます。

活用例③スクリーンショット取得

起動したブラウザ画面のスクリーンショットを取得します。

   //カレントページのスクリーンショットを取得
   File sfile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
   //スクリーンショットファイルの存在を確認するため少し待機する
   try {
       Thread.sleep(15000);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
   //取得したスクリーンショットファイルのパスを表示
   System.out.println(sfile);

取得したスクリーンショットの画像ファイルはTemp領域に保存され、実行後は消えてしまうことに注意してください。画像ファイルとして保存されることをこのコードだけで確認したい場合は、デバッグで止めて確認することができます。テストのエビデンス等でまとめて残しておきたい場合は、画像ファイルのパスを移動させて、所定ディレクトリに残しておくコードを追記する必要があります。
また、ApacheのPOIと組み合わせることでエクセルにスクリーンショットを貼り付けていくこともできます。
複数URLをリスト化してループ処理にすれば、Webサイト全ページのスクリーンショット取得のようなことも一括処理できます。

おまけ

前述したApachePOIとの組み合わせについて、サンプルコードを作成してみました。
細かい解説は割愛しますが、興味のある方は解析や実行などして頂ければと思います。(細かな部分の最適化まで出来ていないのはご容赦ください)
※プロジェクトフォルダ直下に『excel』フォルダを作成し、『Book.xlsx』という空のエクセルファイルをPOIで使用するフォーマット用に用意しておきます。

public class selenium () {
	// フォーマットとなるエクセルファイルのパス
	private static String filePath = System.getProperty("user.dir") + "\\..\\excel\\Book.xlsx";
	// フォーマットとなるエクセルファイルのセル幅(ピクセル)
	private static int cellWidth = 55;
	// フォーマットとなるエクセルファイルのセル高さ(ピクセル)
	private static int cellHeight = 36;

	public static void main(String[] args) {

		Workbook workbook = null;
		try {
			workbook = WorkbookFactory.create(new FileInputStream(filePath));
		} catch (EncryptedDocumentException | InvalidFormatException | IOException e) {
			e.printStackTrace();
		}
		final Sheet sheet = workbook.getSheetAt(0);

		// Chrome制御のためChromeDriverのパスを指定
		System.setProperty("webdriver.chrome.driver", "C:\\chromedriver_win32\\chromedriver.exe");
		// Chromeを起動する
		WebDriver driver = new ChromeDriver();
		// 指定したURLに遷移する
		driver.get("https://www.google.co.jp");
		// カレントウインドウを最大化する
		driver.manage().window().maximize();

		// カレントページのスクリーンショットを取得
		File sfile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

		// 画像オブジェクトクラス
		BufferedImage img = null;
		try {
			img = ImageIO.read(sfile);
		} catch (IOException e2) {
			e2.printStackTrace();
		}

		// スクリーンショットファイルの存在を確認するため少し待機する
		try {
			Thread.sleep(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 取得したスクリーンショットファイルのパスを表示
		System.out.println(sfile);

		// 画像ファイルをByte配列に変換
		InputStream in = null;
		byte[] bytes = {};
		try {
			in = new FileInputStream(sfile);
			bytes = IOUtils.toByteArray(in);
			in.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		// 画像をworkbookに追加
		int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
		// Drawingインスタンスを取得
		Drawing patriarch = sheet.createDrawingPatriarch();
		// ClientAnchorインスタンスを取得
		ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();

		// 画像挿入位置・サイズを指定する
		anchor.setCol1(1);
		anchor.setRow1(1);
		anchor.setCol2(img.getWidth() / cellWidth);
		anchor.setRow2(img.getHeight() / cellHeight);

		// 画像のアンカータイプを設定
		anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);
		// 指定した表示位置に画像を設定
		patriarch.createPicture(anchor, pictureIdx);

		FileOutputStream out = null;
		try {
			out = new FileOutputStream("evidence.xlsx");
			workbook.write(out);
		} catch (IOException e) {
			System.out.println(e.toString());
		} finally {
			try {
				out.close();
				workbook.close();
			} catch (IOException e) {
				System.out.println(e.toString());
			}
		}

		driver.close();
		System.out.println("処理終了");
	}
}

元のサイズを維持したまま貼り付けたかったのですが、画像をエクセルに貼り付ける際に縦横のセル数を指定するというメソッドでした。そのため、元画像のピクセル数を取得した後に1セルのピクセル数で割算し、セル数を算出したりしています。
何か他にスマートな方法があればコメント頂けると喜びます。


以上、Seleniumの環境セットアップ~コード実行、活用例のご紹介でした。
私も初めてSeleniumを触ったので備忘程度に書くつもりだったのが、思いのほか長編になってしまいました。
全編通して読んでくださった方、ありがとうございました!

~会社紹介~
“安定したスタートアップ”を経験できる、アバナード関西の面白さ

記事が皆さんのお役に立てましたらいいねやフォローをお願いします。
内容に関するご指摘や、その他何かございましたら下記に連絡ください。
アバナード関西 井関 純一
junichi.iseki(@)avanade.com / Linkedin

この記事が気に入ったらサポートをしてみませんか?