Xcode7.2+iOS9.2 Simulatorという環境において、KIFでのUIのテストでenterText:intoViewWithAccessibilityLabel:メソッドで入力しようとした文字列とは異なる文字列が入力されてテストが失敗しました。
以下が原因でした。
- Auto correctによって単語が書き換えられた
- Auto capitalizeによって頭文字が大文字に書き換えられた
- 日本語キーボードになっていてアルファベットが日本語変換された
- ハードウェアキーボードがオンになっていた(Bots環境において)
Auto correctによる問題への対策
まず、テキストフィールドのAuto correctが不要であればdisableにするといいです。ただ、disableにしたくなかったので、ググったところKIFのキー入力の遅延設定を変更すれば良いとの情報がありました。
テスト実行前に以下のコードで遅延を設定します。
KIFTypist.setKeystrokeDelay(0.5)
0.5という値はもっと短くしても良いです。短すぎるとAuto correctが発生します。長すぎるとキー入力が遅くなるのでテストの進行に時間がかかるようになります。
Auto capitalizeによる問題への対策
これもテキストフィールドの設定を変更してしまうと問題はなくなります。また、あたりまえですが文字列の先頭文字を大文字で入力すると回避というか、エラーは発生しません。また英単語ではなく日本語文字列だとCapitalizeされないのでエラーが発生しなくなりました。それ以外の方法は分かりませんでした。
日本語キーボードになっている事による問題への対策
方法を検索するとXcodeのSchemeの編集画面のRun->Options->Application LanguageをEnglishに設定すると良いという情報がありましたが、設定しても日本語キーボードになることがあって回避できませんでした。
SimulatorのSettingsアプリで日本語キーボードを削除してもテストを実行してアプリが起動すると日本語キーボードが復活しました。これも駄目です。
環境の設定ではどうにもなりそうにないので、クラスの実装を変更してキーボードを限定してみました。
以下はUIWindowのtextInputModeメソッドをMethod Swizzlingで書き換えています。このコードをテストターゲットに追加します。
# import <objc/runtime.h>
@interface UIWindow (Testing)
@end
@implementation UIWindow (Testing)
+ (void)load
{
Method originalMethod = class_getInstanceMethod(self, @selector(textInputMode));
Method swizzledMethod = class_getInstanceMethod(self, @selector(swizzled_textInputMode));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (UITextInputMode *)swizzled_textInputMode
{
UITextInputMode *reserve;
for (UITextInputMode *mode in [UITextInputMode activeInputModes]) {
reserve = mode;
if ([mode.primaryLanguage isEqualToString:@"en-US"]) {
return mode;
}
}
return reserve;
}
@end
UIWindowを書き換えればおそらく全ての入力コンポーネントのキーボードを変更できるのではないかと思います。少なくともUITextFieldではtextInputModeをen-USだけにしてキーボードをQwertyにする事ができました。またKIFからの日本語文字列の入力も行う事ができました。
ハードウェアキーボードの接続がオンになっている問題への対策
これはローカルでは問題になりにくいですが、Botsでのテストの場合では発生するようです。この問題はSimulatorの設定をコマンドで変更する事で回避する事ができます。
以下のコマンドを実行する事でSimulatorを終了してハードウェアキーボードを接続しないように設定を書き換えます。
osascript -e 'quit app "Simulator"'
defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0
このコマンドを実行すると、ローカルでのテストはSimulatorの起動が必要になるのでBuild Phasesで実行するよりも、Botsのビルド前に実行するように設定すると良いです。
間違いやより良い方法があればコメントおねがいします。