Katalon Studio:スクリーンショットをソケット通信してAIの画像認識結果を取得【Appium,Android,Groovy,Java】



スマホのテスト自動化ツールとして、AppiumとKatalon Studioを以前にご紹介しました。

・Appium:
https://nine-num-98.blogspot.com/2019/05/appium.html

・Katalon Studio:
https://nine-num-98.blogspot.com/2019/05/katalon-studio.html

これを使えば、アプリ起動、スワイプ、タッチ操作、文字入力の各種操作、さらに期待結果(トースト表示の確認など)の検証までの一連の操作を自動化できます。

しかしながら、ブラウザアプリのページ表示機能などをテストする場合では、スマホ画面目視を自動化する必要があります。これは、さすがにAppiumやKatalon Studioの標準機能では検証ができません。

この作業を自動化する方法としては、画像認識AI(機械学習、ディープラーニング)の力を借りるのが適切なのかなと。そこで、先日公開したソケット通信AIです。(後出しになりますが、そもそもこれを作った元々の動機は↑のモバイルアプリテスト自動化にあります。)

https://nine-num-98.blogspot.com/2020/03/ai-socket-01.html
↑の記事で公開した、AIサーバープログラムをラズパイ側で動かしておき、これに対しPC(Katalon Studio)側からスマホ画面画像をソケット通信で送ります。その後、サーバーからの認識結果を受け取れれば、画像目視試験を自動化できるかなと。

システム構成

システムの流れをシーケンス図で書いてみます。




登場人物は、ラズパイ(サーバー)とモバイルテストスクリプトを動かすPC(クライアント)の2つです。

ラズパイ側は、前回のサーバープログラムをそのまま動かします。

一方で、スマホを操作するPC側ですが、こちらは

(1) スマホを自動操作し、検証したいアプリ画面を表示
(2) スマホ画面のスクリーンショットを撮影
(3) スクリーンショット画像をソケット通信
(4) 認識結果を受信して検証

と、なかなかやることが多いです。Katalon Studioを使用すれば、標準機能で(1)(2)はできますが、問題は(3)(4)です。

これは別途、ソケットクライアントプログラムをPC側に実装する必要があります。前回Pythonで作ったソケットクライアントを、Katalon Studioで呼び出すことも考えられますが、ここではKatalon Studioの中で動く、ソケットクライアントプログラムを作ってみました。

Katalon Studioには、ユーザーが独自にプログラムを作成・定義し、テストスクリプトから呼び出せる Custom Keywords という機能があります。これを利用して、ソケットクライアントプログラムをKatalon Studioに実装します。

Introduction to Custom Keywords | Katalon Docs
https://docs.katalon.com/katalon-studio/docs/introduction-to-custom-keywords.html#create-a-package

Katalon Studioではスクリプトを書く際は、JavaまたはGroovyと呼ばれるプログラミング言語を使用する必要があります。Groovyは聞き慣れない言語ですが、これは「JavaをPythonやRuby」のようなスクリプト言語にしてみました。という感じのプログラミング言語です。マイナーな部類とは思われますが、近年人気が出ている言語らしいです。

1. index - Apache Groovyチュートリアル
https://koji-k.github.io/groovy-tutorial/index.html#

Javaの文法。ライブラリがそのまま使えるということで、Javaができる方にはとっつきやすいでしょう。
# 自分はJavaは苦手ですが;

以降、開発環境を示したうえで、クライアント(Katalon Studio)側のテストケースおよび、Custom Keywordsによるソケット通信プログラムを紹介します。

開発環境

■サーバー

ハードウェア
・Raspberry Pi 3 Model B


OS
・Raspbian GNU/Linux 9.11 (stretch)


プログラミング言語、ライブラリ等
・Python 2.7.13
・socket
・Keras 2.1.5
・numpy 1.12.1
・theano 1.0.1
・matplotlib 2.0.0


■クライアント

OS
・Windows 10 Home 64bit

アプリケーション、フレームワーク
・Katalon Studio (Version 5~)
・Appium (Version 1.16.0)

プログラミング言語
・Groovy/Java


■モバイルデバイス

OS
・Android 9

Katalon Studio ソケット通信プログラム


Katalon Studioのテストケースを示します。



Androidのブラウザアプリを自動操作して、目視試験したいページ(yahooなど)を画面に表示。


スクリーンショットを撮影して、画像をソケット通信し認識結果を期待値と比較する内容です。テストケースの各々の処理について何をやってるか説明しますと、以下の通りです。

1 Start Application: ブラウザアプリ起動
2 Binary Statement: スクリーンショット保存先パス定義
3 Wait For Element Present: URLバーが表示されるまで操作待機
4 Tap: URLバーをタップ
5 Set Text: URLバーに閲覧したいホームページのURLを入力
6 Wait For Element Present: ページが表示されるまで待機
7 Take Screenshot: スクリーンショット撮影
8 SocketClient.SendFile: ソケット通信
9 Comment: 認識結果をログ出力
10 Assert Statement: 期待値と認識結果を比較。同じならSuccess。違えばFailure
11 close Application: アプリ自動操作終了

これらのコマンド(Item)に対して定義している要素(Object)、入力引数(Input)、出力(Output)は、スクリプト内で別途独自定義している変数等で、ここでは深追いせず無視してもらって大丈夫です。よくわからないけど、↑の処理をやってるんだなという感じでOKです。このうち、8のコマンド以外はKatalon Studioの標準機能により実装しています。

8 SocketClient.SendFile: ソケット通信
これがCustom Keywordsにより、独自に実装したソケット通信プログラムを呼び出しているコマンドです。SocketClientというクラスにある、SendFileというメソッドを実行しています。メソッドの引数はスクリーンショット画像ファイルパス(sc_file)、返り値はサーバーからの認識結果(res)です。






Custom Keywordsは、Katalon Studio画面の左ペインにあるKeywordsで定義できます。詳細は以下を確認ください。

Introduction to Custom Keywords | Katalon Docs
https://docs.katalon.com/katalon-studio/docs/introduction-to-custom-keywords.html#custom-keywords-in-manual-view

ここでは、SocketClient.groovyというファイルで定義されています。このファイルに書かれているプログラムは先ほど述べたGroovy言語で記述されています。Javaになじんでる方は分かるとは思いますが、このファイル名はクラス名と同じになります。

SocketClient.groovyの内容を以下に記します。

import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.checkpoint.Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testcase.TestCase
import com.kms.katalon.core.testdata.TestData
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

import internal.GlobalVariable

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.io.DataInputStream;

public class SocketClient {
 // 接続先サーバーアドレス
 final static String HOST = "x.x.x.x";
 // 接続先サーバーポート番号
 final static int    PORT = 50001;

 @Keyword
 def SendFile(String filename) {
  // 送信するファイルのパス
  String filepath = filename;
  // 送信するファイルのオブジェクト
  File   file     = new File(filepath);
  // ファイル送信時のバッファ
  byte[] buffer   = new byte[512];
  // サーバー応答受信時のバッファ
  byte[] res_data = new byte[1024];
  // 返り値変数宣言(初期値空文字)
  String str_res = ""

  try {
   // ソケット準備
   Socket sck = new Socket(HOST, PORT);

   // ストリーム準備
   InputStream  fis  = new FileInputStream(file);
   OutputStream sos = sck.getOutputStream();

   //サーバー側の返信受取用
   InputStream sis = sck.getInputStream();

   // ファイルをストリーム送信
   int fileLength;
   while ((fileLength = fis.read(buffer)) > 0) {
    sos.write(buffer, 0, fileLength);
   }

   // ファイル送信終了
   sos.flush();
   sck.shutdownOutput();
   fis.close();

   int readSize = sis.read(res_data);
   res_data = Arrays.copyOf(res_data, readSize);
   str_res = new String(res_data, "UTF-8");
   //System.out.println(str_res);

   // ソケット切断
   sos.close();
   sis.close();
   sck.close();

  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   // サーバーレスポンスを返り値として返す
   return str_res
  }

 }
}


↑はこちらの記事に書かれてある、Javaのソケット通信プログラムを参考にして実装しました。
http://tqgf.hateblo.jp/entry/2015/10/07/095144

GroovyではJavaのプログラムやライブラリも普通に動くという特徴があります。上記プログラムはGroovyで書いたとはいえ、ほぼJavaです。Javaらしくオブジェクト指向ということで、クラスとそれが内包するメソッドを定義する形で書いています。

ここでは、クラスとしてSocketClientを定義しています。定数フィールドとして、接続先サーバーのIPアドレス・ポート番号を定義しています。使用の際は、これらの設定がまず必要です。

次のメソッドですが、ここで実際にソケット通信のクライアント処理が定義されています。

 @Keyword
 def SendFile(String filename) {


このメソッドの実行は、テストケース側で、

SocketClient.SendFile

のようにして、クラス名.メソッド名で呼び出すことができます。SendFileメソッドで記述している内容は、以前にPythonで書いたものとほぼ同じです。Pythonのほうが遥かに書きやすくて好きですね。(Java好きの方にはすみません;)

Python版と同じく、留意すべき点としては、

   // ファイル送信終了
   sos.flush();
   sck.shutdownOutput();
   fis.close();

の箇所です。サーバー側にデータ送信完了を伝えるために、送信路を閉じる処理

sck.shutdownOutput();

を行う必要があります。


このプログラムの出力(サーバーからの認識結果)に対し、検証を後続するテストケースで実施しています。

9 Comment: 認識結果をログ出力
10 Assert Statement: 期待値と認識結果を比較。同じならSuccess。違えばFailure
11 close Application: アプリ自動操作終了

10の処理で、認識結果が期待値と異なれば、テストNGということになります。yahooのページを開く試験でNGであれば、ページがちゃんと開けていないなど、ブラウザの表示機能のバグなどがこのテストケースの実行で判明します。

Katalon Studio や Appium では対応できない目視試験に対しては本記事のように、画像認識AIとソケット通信で対応するのも一つの有力な方法かなと。

参考になれば幸いです。

スポンサーリンク