【Appium】モバイルSafari上でテストを実行してみた
先日、iOSでAppiumを試してみたんですが、今回はiOSでやってみました。
お題
実機/シミュレータ上でモバイルSafariを起動しテストを実施する。
Appiumって?
- 作者: Manoj Hans,太田健一郎,児島修
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/11/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Appiumとは、iOSおよびAndroidプラットフォーム上で動く - ネイティブアプリ - モバイルウェブサービス - ハイブリッドアプリ 等を自動化するオープンソースのツールです。
よくまとめられているコチラの記事をご参照ください。
Design(公式)
http://appium.io/slate/en/master/?ruby#appium-design
Concepts(公式)
http://appium.io/slate/en/master/?ruby#appium-concepts
なぜ必要に?
現在、広告配信タグ(モバイルウェブサービス用)のE2EテストにNightmareを使用しています。 しかし、 モバイルSafariでしか発生しない事象 (Mac Safariでも再現しない)にぶち当たり、実機(シミュレータ)を使用したE2Eテストの必要性が出てきました。 また、せっかくなら広告配信SDK(ネイティブアプリ用)のテストにも使っていきたいと思い。 そこで、SeleniumぽくてWebDriberの流れを組むやつをチームメンバーに紹介されたので試してみました。
Appium環境を構築するさいにiOSで注意すべきこと
- Mac環境のあるサーバーをたてないと実機/シミュ−レーターでのテストができない
- Xcode8に対応していない(時間の問題なんだろけど)
必要な条件
http://appium.io/slate/en/master/?javascript#requirements
Appiumサーバを用意する
CUIでやるなら
その上で下記からOS毎のセットアップにうつる http://appium.io/slate/en/master/?javascript#appium-platform-support
僕はなかなかうまくいかなくて・・・・
GUIでやってみる
githubで生成するよりも、GUI版をダウソしてくると少しバージョンが古い。 実践 Appiumで紹介されているバージョンに近いのはこっち。
ダウソ
latest versionをダウンロードする
Appium GUIを起動
v1.5.3のAppium GUIを起動してみた。
Appium GUIの設定
Basic
Adbanced
- XcodePath Xcodeを複数入れている場合は使用するやつに変更する
Appium GUIよりAppiumサーバを起動
Launch
ボタンをタップする。ダーッと出てくるので待つ。
テストを実行する
下記動かせるように適当にNode.js環境を整備した上で、mocha
で動かしてみてください。
元ネタは、関数を分割してしまっているのですが、見通しを良くするために僕のお試し版は、下記をご覧の通り1つの関数に全部つめこんじゃいました。
"use strict"; var wd = require("wd"); require('colors'); var chai = require("chai"); var chaiAsPromised = require("chai-as-promised"); chai.use(chaiAsPromised); var should = chai.should(); chaiAsPromised.transferPromiseness = wd.transferPromiseness; describe("ios safari", function () { this.timeout(300000); var driver; before(function () { var serverConfig = { host: 'localhost', port: 4723 }; driver = wd.promiseChainRemote(serverConfig); var desired = { browserName: 'safari', 'appium-version': '1.6', platformName: 'iOS', platformVersion: '9.3', deviceName: 'iPhone 6s', app: undefined }; return driver.init(desired); }); after(function () { return driver .quit(); }); it("should get the url", function () { return driver .get('https://www.google.com') .sleep(1000) .waitForElementById('lst-ib') //.waitForElementByName('q', 5000) .type('cyberagent') .waitForElementByClassName('kpgrb') //.waitForElementByName('btnGNS') .click() .waitForElementByLinkText('サイバーエージェント') .click() .sleep(5000) .saveScreenshot('test.png'); }); });
https://github.com/toguri/sample-code/blob/master/sample-code/examples/node/ios-safari-google.js
締め
まだ、うまくテストコードが書けてないけど、テストを実行するとシミュレータが起動してテストコードに書いて有る内容通りに、勝手に動きます。
【iOS10】ATSのおさらい 2016年末
この記事は「iOS その2 Advent Calendar 2016」10日目の記事です。
テーマは、 2016年中 にiOSにおけるATSをおさらいしよう! です。
自己紹介
私は、株式会社サイバーエージェント CA ProFit-X という広告プロダクトで、メディア様の収益を最大化することを目標にエンジニアをやってます。 CA ProFit-X は、モバイル向けネイティブ広告(主にインフィード広告)専業のSSP事業者なのです!
お題
モバイルアプリ/モバイルウェブサービス上で広告運用時に気にしておきたい ATS について、今回は最新OSである iOS10 にターゲットを絞り、お話ししたいと思います。
ATSとは?
ATSは、App Transport Securityの略で、2015年にiOS9がリリースされた際に導入されたセキュリティ仕様です。
詳しい仕様は コチラ(Apple Developer Library)です。
簡単に言うと、アプリとWEBサービス間の接続のプライバシーと、データの整合性を向上を目的に、セキュリティ仕様に準拠していない接続は認めないってことです。
例えば下記とか。
サーバー証明書に関する要件
Webサーバーに関する要件
2017年からは対応が必須になる
原則対応が必須になります。新規アプリ/既存アプリ問わずApp Storeに提出するには ATS有効化が必須条件 です。
対象
まぁ、ほとんど全部ですね。
- iOS9.0以上
- WKWebView
- UIWebView
- NSURLSession
- NSURLConnection
ATSを無効化するには?
基本的に、セキュリティ仕様に準拠しとけば良いのですが、いちおう。
細かいキーの仕様についてはコチラです。
NSAllowsArbitraryLoads
- デフォ値は
No
Yes
に設定した場合NSExceptionDomains
に設定したドメインのに対するネットワーク接続がATS無効化されて可能になる- App Storeへアプリを提出する際にAppleに対する説明が必要になる
- (後述する)NSAllowsArbitraryLoadsInWebContentが
Yes
の場合、このキーは無効になる
NSAllowsArbitraryLoadsInWebContent
- デフォ値は
No
Yes
に設定した場合- 下記のネットワーク接続がATS無効化されて可能になる
- WKWebView
- UIWebView
- つまり、NSURLSession/NSURLConnection接続はATS有効化のまま、WebViewのみATS無効化が可能
- 下記のネットワーク接続がATS無効化されて可能になる
- iOS10以上が対象、iOS9以下については本キーを
Yes
にした上で、NSAllowsArbitraryLoads
も設定する
(´ε`;)ウーン…
まとめ
iOS10なら、WebViewでATSを無視できるっちゃできるのね。
でも、これはAppleの独断とかではなく、セキュリティ的に安全な配信をしていこうぜって大きな流れの1つなわけで。
GoogleもHTTPSサイコー!って言ってるわけだし。
ATS対応ができねーとかケチくさいこと言わずに、堂々とやってやりましょうよ!
Cycript入門 〜アプリをハックしてデバッグしてみよう〜
はじめに
この記事は、 僕が主宰する 『スマートデバイス向けアプリのマネタイズ研究と実践開発』ゼミの 活動記録です。
ゼミについて
株式会社サイバーエージェント アドテク本部 アドテクスタジオ内の活動です。
詳しくは、ゼミ『スマートデバイス向けアプリのマネタイズ研究と実践開発』まとめをご参照ください。
用意するもの
- ジェイルブレイク済みのiOS端末
- Cydiaがインストールされている
下記のドキュメントはCydiaを前提としています。
目的
Cycriptは、既存のアプリにコードを突っ込むことができるので、リリース後のアプリに対してもデバックに使えるかなと思っています。
このツールは、Objective-CとJavaScriptのハイブリッドのツールらしく、ターミナルにObjective-Cのコードを入力するだけでそのアプリ内で実行することができるらしい。
目標
参加者全員が 適当なアプリのボタンやラベルの内容を外から変更する を達成する
Cycript入門
以下の操作について、ジェイルブレイク前提であり、自己責任でお願いします。
参考になったサイト
Cycript公式 http://www.cycript.org/
Realmのサイトを参考に進める https://realm.io/jp/news/conrad-kramer-reverse-engineering-ios-apps-lyft/
Cycript Tricks http://iphonedevwiki.net/index.php/Cycript_Tricks
主なオペレーション
- Cydiaを使う
- Cycriptをインストールする
- OpenSSHをインストールする
- iPhoneにMacからSSHでログインする
- Cycriptでアプリを操作する
- Process Injection
- アプリの画面構成をハックする
- ボタンの色やテキストをハックする
- ボタンイベントをハックする
Cydiaを使う
CycriptやOpenSSHをインストールするのに使用します。僕の脱獄方法の場合です。
Cycriptをインストールする
今回のお題でもあるこいつをインスールします。
OpenSSHをインストールする
ついでにOpenSSHもインスールします。
iPhoneにSSHでログインする
自分のMacのターミナルから、iPhoneのIPアドレスを指定してsshログインします。初期パスワードは、alpine
です。
$ ssh root@[IPアドレス] root@IPアドレス password:[alpine] root#
Cycriptでアプリを操作する
操作したいアプリのプロセスをチェックし、cycriptで指定して起動する。
下記では、UBER
を題材にすすめます。
重要 下記作業前にUBERをインストール&起動しておきます。
起動直後の画面はこんな感じ。
Process Injection
cycript -p
を使って、プロセスにアタッチします。
root# ps aux | grep UberClient mobile 1660 0.0 4.4 815456 90912 ?? Us 6:49PM 0:02.64 /var/containers/Bundle/Application/E3330-CBE5-40AC-8365-66E075C6C04C/UberClient.app/UberClient root# cycript -p 1660 cy#
アプリの画面構成をハックする
cy# UIApp.keyWindow.recursiveDescription() @"....現在表示中の画面構成を再帰的に表示されます、結果はキャプチャのみで"
ダーッとでます
中央の UBER 画像をハックする
こんな感じで、オブジェクトを取得するには、画面構成からIDを探してインスタンスを生成したります。
cy# var imageView = new Instance(0x151101f30); cy# var droidUrl = [NSURL URLWithString:@"https://andropp.jp/webapp/wp-content/uploads/2014/11/android-wallpaper5_2560x1600_1.jpg"]; cy# var droidData = [NSData dataWithContentsOfURL:droidUrl]; cy# var droidImage = [UIImage imageWithData:droidData]; cy# imageView.image = droidImage;
UBERアイコン画像が消えて、droidくんになってもーたw
登録ボタンをハックする
var signupButton = new Instance(0x14fe47730); [signupButton setTitle:@"hogeeee" forState:UIControlStateNormal];
と入力すると 登録
という文字が....
....hogeeee
になってるw
ちなみに、登録ボタンを端末に触らずに押しちゃうには....
cy# [signupButton sendActionsForControlEvents:UIControlEventTouchUpInside];
これで、起動!
まとめ
iOS端末をジェイルブレイクしないといけないので、少し敷居が高い。
Cycriptを使ったハックは、既存アプリの研究を目的とした活用に向いてそう。
また、アプリ側にバックドアを意識した仕掛けを用意しておけば、強力なデバッグができそう(そんな仕掛け、怖くてアレだけど)。
iOS10でIDFAを取得できるか!?
オプトアウトした端末のIDFAは取得できない?
iOS10 アップデート以降、オプトアウトした端末のIDFAは取得できない
といった情報が、巷でまことしかやに囁かれている。
僕自身の iOS10 に端末をアップデートし、検証を試みた。
検証しみてる
iOS9 まではユーザが自身の端末上でオプトアウトしても、IDFAの取得自体は可能だった。
しかし、 iOS10 アップデート(2016年9月14日 日本時間2時)以降、有効なIDFAが取得できない。
もう少し詳細に書くと、 文字列は取得できるが、一意のユーザーを表すものではない。
実際に、オプトアウトした後に取得した値は、00000000-0000-0000-0000-000000000000
というゼロパディングされた文字列が返ってきてた。
cf. ASIdentifierManager Overview 3. Get the advertising identifier using the advertisingIdentifier property (note that when ad tracking is limited, the value of the advertising identifier is 00000000-0000-0000-0000-000000000000). https://developer.apple.com/reference/adsupport/asidentifiermanager
iOS端末でオプトアウトするための方法
[設定] - [プライバシー] - [広告] - 「追跡型広告を制限」 をオンにする
まとめ
大抵の広告事業者は端末側でIDFAとオプトアウトフラグの両方を取得して、広告配信サーバへ投げているはず。 CV計測目的の場合、広告配信という目的の延長線上としてオプトアウトフラグの状態に関わらずIDFAを使用していると思われる。 たぶん、問題の焦点はこの世の中でオプトアウトしているユーザが何人いるのかによって、影響度合いが大きく変わるところだと思う。
Swift Advent Calendar 2014
13日目を担当しました。
iOSの6日目に続き、今年2度目の当番日をクリアしました。
よし後は来週のAndroidでおしまいや!!
ちょうど? 注文していたSwift本が届き、これも何かの縁かな。
- 作者: 荻原剛志
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2014/12/10
- メディア: 大型本
- この商品を含むブログ (1件) を見る
最近、疲れているのか
アマゾンポチがアマゾンチ◯ポに見えて仕方がない
— toguri (@neiraza) December 12, 2014
iOS Advent Calendar 2014
6日目を担当しました。
ネイティブアドのすゝめ(iOS) - Qiita
2年ぶりのAdvent Calendarですが、楽しめました。
次はSwiftとAndroidの当番日までに準備しなきゃ!
僕が前の会社に入社したきっかけが、水野さんに会いに行こうと思ったからでした。
その水野さんが書いた本です!
- 作者: 水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/11/21
- メディア: 大型本
- この商品を含むブログ (1件) を見る
↑の本を Web API のAdvent Calendarでウサ耳様がオススメしてました!