ラベル テスト の投稿を表示しています。 すべての投稿を表示
ラベル テスト の投稿を表示しています。 すべての投稿を表示

2014年3月16日日曜日

Calabash-Androidを利用してAndroidのシナリオテストを日本語で書いてみる

このエントリーをはてなブックマークに追加 はてなブックマーク - Calabash-Androidを利用してAndroidのシナリオテストを日本語で書いてみる

Androidのシナリオ自動化テストで使えるCalabsh-Andoridを利用してみたのでその時のメモ。calabash-androidのインストールを行い、HelloWorldアプリをエミュレーターで動かし、日本語によるシナリオテストできるまでを記載します。(ググれば分かりそうな所は割愛)

calabash-android

目次

  1. Calabash-Androidとは
  2. Calabash-Androidのインストール
  3. HelloWorldアプリの作成
  4. Androidエミュレーターの作成、起動
  5. 試験(cucumber)のスケルトン作成
  6. keystoreの設定
  7. テストの実行
  8. テストを日本語化する
  9. Tips

1.Calabash-Androidとは

こちらの資料がとても分かりやすかったです。

Calabash-AndroidでBDDしようぜ!

ざっくり特徴としては

  • Androidのシナリオテストを実行するライブラリ
  • 現在も開発が続いている(2014年3月16日時点)
  • テストはCucumberで書く
  • テストで日本語が書ける

などが特徴でしょうか。 あと特に良いなと思った点としてコード書かない人でもテストが書ける事です。

# language: ja
フィーチャ: 初期画面表示確認を行う
        アプリのユーザーとして初期画面表示を行う。
        なぜならアプリ起動時に表示するからだ。

シナリオ: 初期画面を表示する
        ならば"Hello world!"と表示されていること
        ならばスクリーンショットを撮る

みたいな書き方が出来るのでテスターの人でも書けるのが特に良いなと。(他のテストライブラリについてそんなに詳しく分かりませんが) あとで見た人もとても分かりやすい。

2.Calabash-Androidのインストール

公式ドキュメントはこちら。

Calabash-AndroidはRubyのGemで提供されているので、Rubyのインストールが必要です。また、以下が必要となります。

  • Ruby(1.8.7以上)
  • Ant
  • Java
  • AndroidSDKのインストール、ANDROID_HOMEの設定

自分はMacOSXで設定しましたが、LinuxでもWindowsでも条件が揃っていれば動作可能かと思います。

各インストールの詳細は割愛。 インストール後、各コマンドのパスが通っているか確認。

$ruby -v
ruby 1.9.3p385 (2013-02-06 revision 39114) [x86_64-darwin13.1.0]

$java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

$ant -version
Apache Ant(TM) version 1.9.3 compiled on December 23 2013

$echo $ANDROID_HOME
/Applications/adt-bundle-mac-x86_64-20131030/sdk

ANDROID_HOMEはsdkの所を指定しないと駄目なようなので注意。

上記が完了したら、以下コマンドでCalabash-Androidをインストール。

$gem install calabash-android

確認。

$gem list --local |grep android
calabash-android (0.4.21)

3. HelloWolrdアプリの作成

テスト対象とするAndroidアプリを作成しましょう。とりあえず自分はHelloWorldアプリを作りました。ここも詳細は割愛。

この際の注意点としてAndroidManifest.xmlandroid.permission.INTERNET を設定しておいてください。

Calabsh-Androidではhttpを使ってテストしているっぽいのでこれをやっておかないと失敗します。

4. Androidエミュレーターの作成、起動

Androidエミュレーターを作成して起動しておいてください。詳細は割愛。 実機の場合、USB接続してadb devicesコマンドで認識できていればOK。

テストしたいアプリがインストール、起動出来る事を確認しておくと良いと思います。

また、エミュレーター起動時にUse Host GPUを使うと後述するテスト時のスクリーンショットを撮るときに黒くなってしまうので注意です。

5. cucumberのスケルトン作成

試験をする為のスケルトンファイルを作成します。テストしたいAndroidプロジェクト配下(AndroidManifest.xmlがある場所)に移動して、calabash-andorid genコマンドを実行します。

$cd workspace/[YourProjectName]
$calabash-android gen

とするとスケルトンが作成されます。

features
|_support
| |_app_installation_hooks.rb
| |_app_life_cycle_hooks.rb
| |_env.rb
|_step_definitions
| |_calabash_steps.rb
|_my_first.feature

my_first.featureが試験項目になるのですが、こちらの内容をHello world!と画面に表示されている事という内容に変更します。

Feature: Login feature

  Scenario: As a valid user I can log into my app 
    Then I see "Hello world!" 

本当はFeature,Scenarioの場所も変えた方が良いのですが、とりあえず動かしたいので無視。(日本語化に関しては後述)

6. keystoreの設定

テスト実行時にテスト対象のapkと同様の署名されたテストアプリを同時にインストールします。

上記より、どのkeystoreを使ったかを教えてあげる必要があります。

$calabash-android setup

上記コマンドを実行するとkeystoreの場所、alias、パスワードを聞いてくるので入力します。 入力が終わるとカレントディレクトリにcalabash_settingというのが出来ており、こちらに入力した情報があるのが確認出来ます。

7. テストの実行

さあ、テストを実行してみましょう!calabash-androidコマンドを実行し、引数にテストしたいapkを指定します。

$calabash-android run bin/MainActivity-debug.apk
Feature: Login feature

  Scenario: As a valid user I can log into my app # features/my_first.feature:3
1135 KB/s (556187 bytes in 0.478s)
1706 KB/s (277892 bytes in 0.159s)
    Then I see "Hello world!"                     # calabash-android-0.4.21/lib/calabash-android/steps/assert_steps.rb:5

1 scenario (1 passed)
1 step (1 passed)
0m37.799s

とすると色々文字が出て最後に成功(pass)しているのが確認できます。なお、-vオプションを付けるとverboseで詳細が表示されるのでうまく動かない時はこちらを付けるのがおすすめです。

先ほど編集したmy_first.featureのThen I see “Hello World!”の箇所をThen I see “test!!!”とするとテストが失敗する事からもテストがしっかり実行できている事が確認できます。

$calabash-android run bin/MainActivity-debug.apk
Feature: Login feature

  Scenario: As a valid user I can log into my app # features/my_first.feature:3
1907 KB/s (556187 bytes in 0.284s)
1668 KB/s (277892 bytes in 0.162s)
    Then I see "test!!!"                          # calabash-android-0.4.21/lib/calabash-android/steps/assert_steps.rb:5
      Action 'assert_text' unsuccessful: Text'test!!!' was not found (RuntimeError)
      features/my_first.feature:4:in `Then I see "test!!!"'

Failing Scenarios:
cucumber features/my_first.feature:3 # Scenario: As a valid user I can log into my app

1 scenario (1 failed)
1 step (1 failed)
0m46.468s

8.テストを日本語化する

今書いてあるテストはあくまで英語なので日本語でも出来るようにします。 まず、featureファイル(シナリオ)を日本語化します。

# language: ja
フィーチャ: 初期画面表示確認を行う
        アプリのユーザーとして初期画面表示を行う。
        なぜならアプリ起動時に表示するからだ。

シナリオ: 初期画面を表示する
        ならば"Hello world!"と表示されていること
        ならばスクリーンショットを撮る

1行目で日本語での予約語を使いますよ、という事を宣言しています。(Feature:フィーチャ、Then:ならば、などなど)

ただし、これでテストを実行しても「表示されている事」、「スクリーンショットを撮る」などの記述が何の操作に対応するか不明であるため、動きません。 そこでfeatures/step_definitions/calabash_steps.rbファイルを編集します。

# coding: utf-8
require 'calabash-android/calabash_steps'

ならば /^"(.*?)"と表示されていること$/ do |text|
  step %{I should see "#{text}"}
end

ならば /^スクリーンショットを撮る$/ do
  step %{I take a screenshot}
end

こんな感じで日本語で認識させたい文言を書き、次の行に具体的に実行する処理を記載します。 step hogeで出来る処理の一覧は以下にあります。(hoge秒待つ、fugaボタンを押すなど色々あります)

calabash-android / ruby-gem / lib / calabash-android / canned_steps.md

また、最初に紹介したslideshareを書いてくれた方がstepファイルを日本語化したものをGistにおいてくれているみたいなのでこれを使っても良いかと思います。(未検証とのことですが、かなり助かります。)

patorash / common_steps.rb

準備ができたのでテストを実行してみます。

$calabash-android run bin/MainActivity-debug.apk
# language: ja
フィーチャ: 初期画面表示確認を行う
  アプリのユーザーとして初期画面表示を行う。
  なぜならアプリ起動時に表示するからだ。

  シナリオ: 初期画面を表示する               # features/my_first.feature:6
1558 KB/s (556187 bytes in 0.348s)
1397 KB/s (277892 bytes in 0.194s)
    ならば"Hello world!"と表示されていること # features/step_definitions/calabash_steps.rb:4
    ならばスクリーンショットを撮る             # features/step_definitions/calabash_steps.rb:8

1 scenario (1 passed)
2 steps (2 passed)
0m44.955s

成功しました!結果もすごい分かりやすい!撮ったスクリーンショットはカレントディレクトリにscreenshot_0.pngとかで配置されています。

試験シナリオを増やす場合にはfeature/**.featureというファイルをシナリオ分作成していけばOKで、日本語で実施したい処理を増やしたい場合にはfeatures/step_definitions/calabash_steps.rbに記述を増やしておけばOKです。

9.Tips

  • calabash-android run bin/MainActivity-debug.apk -v --format html --out reports.htmlというような書き方で結果をHTML出力できる
  • debugビルドしたアプリをインストールした状態でreleaseビルドしたアプリをテストしようとすると証明書違うよって怒られる事があるのでその場合には一度アプリを削除するなどが必要。(基本的にはuninstallコマンドが先に走るので大丈夫なはず)
  • テスト用にインストールしているアプリはtest_servers/配下に存在する
  • adb installでアプリをインストールしているが、adb -r installにしたい場合にはfeatures/support/app_installation_hooks.rbのinstall_appという記述をupdate_appとすれば良い。(プリインアプリなどアプリが削除できない場合に有効)

2013年6月24日月曜日

[Tizen]Tizenネイティブアプリ開発でのUnitテストの実施

このエントリーをはてなブックマークに追加 はてなブックマーク - [Tizen]Tizenネイティブアプリ開発でのUnitテストの実施

Tizenネイティブアプリ開発時のUnitテストについて試してみたのでメモ。

Tizenのネイティブアプリ開発ではC++での開発となりますが、テストはどうするのかというと標準でGoogle C++ Testing Frameworkが同梱されており、公式ドキュメントでもこれを使うような記述があるのでこれを利用するのが一般的ではないかと思われます。

Unit Test Tool

上記リンクからTizen Native App Programing→IDE and Tools→Unit Test Toolと辿るとTizen公式ドキュメントが確認できます。

今回の例ではサンプルアプリにクラスを追加し、そのクラスに対してテストを行ってみます。 手順は以下の通りです。

  1. テスト対象プロジェクト作成(サンプルアプリ)
  2. テストプロジェクトの作成
  3. テストプロジェクトの編集
  4. テストプロジェクトの実行

なお、公式ドキュメントにテストの項目の欄で以下の記述があるため、注意が必要ではあります。

  • The unit test tool is designed to support only functional testing.
  • The unit test tool is not an OSP-based application. Therefore, certain methods related to the OSP application framework, such as the methods of the Tizen::Base::String class, can behave incorrectly.

超適当な意訳

  • functionテストのみがサポートですよー。
  • このUnit Test toolはTizen用のテストツールって訳じゃないよ。なので、Tizen::Base::Stringクラスとかいくつかのメソッドなどは誤った動作するかと思われます。

ま、まじでか。 とか思って試しにTizenのStringを利用したテストコード書いてみましたが、一応大丈夫でした。 保証はできないってことか、な。

確認環境など

  • MacOSX 10.8.4
  • TizenSDK2.1(IDEやSDKなどはインストール済み)

1.テスト対象プロジェクト作成(サンプルアプリ)

まずはテスト対象のHellWorldプロジェクトをTizenIDEを利用して作成します。

  • File→New→Others
  • Tizen→Tizen Native Project
  • Templateタブを選択→Tizen Native→Form-based Application→With SceneManagerを選択。Project Nameは任意の名前でOKですが、本例ではHelloWorldとします。

これでとりあえずプロジェクトができます。

次にUtilクラスを追加します。

とりあえずこんな感じでメソッドを2つ作ってみました。(C++初心者なので書き方がまずいかもしれませんが、とりあえず許して下さい。。。)

Util.h

#ifndef UTIL_H_
#define UTIL_H_
#include <FBase.h>

class Util {
public:
    int Sum(int x, int y) ;
    void AppendWorld(Tizen::Base::String& base);
};


#endif /* UTIL_H_ */

Util.cpp

#include "Util.h"

int Util::Sum(int x, int y) {
    return x + y;
}

void Util::AppendWorld(Tizen::Base::String& base) {
    base.Append("World!");
}

Sum関数では引数に渡した2つの引数の加算を行った結果を返却します。

AppendWorld関数では引数に渡したTizen::Base::Stringクラスの参照引数を利用してAppendメソッドを呼び出して、引数に渡された文字列の末尾に“World!”という文字列を追加します。

今回は上記2つのメソッドに対してそれぞれテストコードを書いてみます。

2.テストプロジェクトの作成

Tizenでテストを行う場合、テスト対象のプロジェクトとは別に新規にテスト用プロジェクトを作成する必要があるようです。 以下の方法で作成を行います。

  • File→New→Others
  • Tizen→Tizen Native Unit Test Project
  • Select the Tizen Project for testの箇所でHelloWorldを選択。

これでHelloWorldプロジェクのテストプロジェクトの完成です。 デフォルトで以下のようなテンプレートテストコードが作成されます。

HelloWorldTest.cpp

include "tizenx.h"
#include "Util.h"
#include "HelloWorldPanelFactory.h"
#include "HelloWorldMainForm.h"
#include "HelloWorldFrame.h"
#include "HelloWorldFormFactory.h"
#include "HelloWorld.h"
#include "AppResourceId.h"

#include <gtest/gtest.h>

class TestSuite : public testing::Test
{
    protected:
    // virtual void SetUp() will be called before each test is run.
    // You should define it if you need to initialize the variables.
    // Otherwise, you don't have to provide it.
    virtual void SetUp()
    {

    }
    // virtual void TearDown() will be called after each test is run.
    // You should define it if there is cleanup work to do.
    // Otherwise, you don't have to provide it.
    virtual void TearDown()
    {

    }
};

// When you have a test fixture, you define a test using TEST_F.
// Otherwise, you define a test using TEST.
TEST_F(TestSuite, test01)
{
    ASSERT_TRUE(true);
}

TEST_F(TestSuite, test02)
{
    ASSERT_TRUE(false);
}

先ほど作成したUtilクラスのヘッダファイルもincludeされているのでテストコードが追加できそうです。

3.テストプロジェクトの編集

HelloWorldTest.cppにSum関数、AppendWorld関数のテストコードに以下のように追加(編集)します。 なお、test02はデフォルトだと実行するとNGとなってしまうので、こちらも変更します。

TEST_F(TestSuite, test02)
{
    ASSERT_TRUE(true);
}
TEST_F(TestSuite, test03)
{
    Util *p = new Util();
    ASSERT_EQ(3, p->Sum(1, 2));
    delete p;
}

TEST_F(TestSuite, test04)
{
    Util *p = new Util();
    Tizen::Base::String hello = Tizen::Base::String("Hello");
    Tizen::Base::String helloworld = Tizen::Base::String("HelloWorld!");
    p->AppendWorld(hello);

    ASSERT_EQ(helloworld, hello);
    delete p;
}

test03ではSum関数の引数に1と2を渡し、結果で3がかえってくる事を確認しています。

test04ではHelloという文字列のTizen::Base::Stringクラスを作成し、AppendWorld関数を利用する事で“HelloWorld!”という文字列になる事を確認しています。

なお、利用しているGoogle C++ Testing Frameworkについては以下の翻訳サイトを参考にさせて頂きました。(まだ全然読めてないですが)

Google C++ Testing Frameworkをはじめよう

4.テストプロジェクトの実行

いよいよテストを実行します。 テストの実行及び結果の確認はTizenIDEで実施できます。

テスト対象のプロジェクトのビルドをしてからテストコードの存在するプロジェクトをビルドします。

  • HelloWorld→右クリック→Build Project
  • HelloWorldTest→右クリック→Build Project

なお、先にHelloWorldTestの方をビルドすると以下のような先にテストする方のプロジェクトしろよ的なメッセージが出ます。その場合、メッセージの通り先にテスト対象のビルドを実施し、その後再度テストプロジェクトのビルドをすればOKです。

次にエミュレーターを起動します。 個人的にはエミュレーターなしでやりたかったのですが、IDEから実行するときは必要だったのでやっておきます。

さてこれで準備がすべて終わったのでいよいよテストを実行します。

  • HelloWorldTest→右クリック→Run As→Tizen Native Unit Test Application

これで実行されるのでしばし待ちます。

結果はIDE上のTest Resultで確認できます。

また、上記左にあるTest Exploerを利用すると特定のテストコードのみの実行ということも可能です。

Tips

設定を行う事で以下が可能なようですが未確認。

  • HelloWorldTest→右クリック→Run As→Run Configurations

以下設定可能項目。
  • Run Disabled Tests
  • Shuffle Tests
  • Don’t Print Elapsed Time
  • Generate and XML Report

Jenkinsとかとも連携さたいので今後はCLIからの実施方法なども確認したい。