20210802のAndroidに関する記事は3件です。

【Kotlin】must be locked before it can be used to compute a classpath! と表示されコンパイル出来ない場合の対処法

解決策① gradle.properties内のconfigureondemandをFalseにする。 org.gradle.configureondemand=false  解決策② Build.gradle.kts→Build.gradleに変更する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

QiChat MANIAX(2) ヘッダのキーワードを網羅する??

はじめに 今回はQiChat MANIAXの続編です!ヘッダのキーワードについて、詳しく見ていきましょう?‍??‍? conceptで同類を定義する??? conceptは、リストの単語とフレーズを定義するものです。下記のように使います↓ concept:(name) [word1 word2 "word3 word4"] word1とword2は個々に独立した単語 word3とword4は複数の単語によるフレーズ。間に合うスペースのある単語を一つのフレーズとして扱う場合は、ダブルコーテーション(")でくくってください nameはリストにつけるコンセプト名。コンセプトを使用するときに使います ⚠️注意 フレーズとは文章ではなく単語の集まりであり、句読点は自動的に排除されます。 コンセプトはどの単語でもglobalであり、異なるTopicでも使用可能です? 以下は使用例と実行例です。 topic: ~introduction () concept:(greetings) ^rand[おはよう スラマッパギ "許して ヒヤシンス"] concept:(phoenix) [銅の 金の] 鳳凰 concept:(food) [リバイアサン アマビエ ~phoenix] u:(~greetings) ~greetings u:(_~food が食べたい) $1 は調理済みです u:(お腹すいたな) ~food 捌いてきましょうか ちなみに^randは、選択をランダムにしてくれます? ^randなしの場合、選択肢の中身は順番に選択されていきます。 $\tiny{アマビエローフ}$ 後出しできるdynamic topic: ~dynamic() dynamic:mp3 u:({そうだな}_~mp3 ["かけて お願い" 聴きたい] ) $1 再生します。ぷわーん QiChatbot qiChatbot = ...; EditablePhraseSet editablePhraseSet = qiChatbot.dynamicConcept("mp3"); List<Phrase> phrases = new ArrayList<>(); phrases.add(new Phrase("マリークレールアラン")); phrases.add(new Phrase("グレングールド")); phrases.add(new Phrase("エンリコピエラヌンツィ")); editablePhraseSet.addPhrases(phrases); 基本的にはstaticを使う方が良いですが、GitのMastering dynamic conceptで体験できるように後から単語を追加することができます➕ ⚠️注意 dynamicのコンセプトにあまり多くの単語やフレーズを追加すると、読み込み時間に影響します。例えば数千の単語やフレーズを含むdynamicのコンセプトは、読み込みに数分を要するでしょう?? それぞれの単語やフレーズを読み込むためにPepperはリスニングの機能を停止するので、多すぎる単語やフレーズの読み込みはユーザー体験の質を劣化させてしまうのです。 descriptionで話を思い出す? descriptionに記述した内容は、$Dialog/FocusDescriptionで呼び出すことができます。使用例は以下の通りです↓ description: イルミネーション u:(天の川を航海できたら星が採れるのに) 月には海がありますよ u:(淡水魚いるかな) それを言うなら海水魚だと思います u:(何の話だっけ) $Dialog/FocusDescription の話です topicでネーミングセンスを試される? Topicの名前を決定します。nameの部分です↓ topic: ~name () 名前は一つしか持てないため、ポチやタマなどいい加減な命名は避けましょう。 $\tiny{ストレルカとベルカに憧れるポチと、音楽性の違いからブレーメンの音楽隊を脱退してギタリストになったタマ}$ あとがき 今回もPepperSDKforAndroidを参考に書かせていただきました。 次回のQiChat MANIAXはルール編です。下の画像は網の目を潜る(物理)Pepperです。 それでは!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】UI テストの基本と処理の待ち合わせ方法

やりたいこと 以下のようなアプリに対して Espresso を使った UI テストを作成します。 (リポジトリはこちら) ユーザー名を入力してログインできる ユーザー名が入力されていないと注意メッセージが表示される ログインには3秒かかる ログイン後、メッセージが表示される 初期画面 ユーザー名なしでクリック ログイン中 ログイン後 ライブラリの追加 UI テストに必要なライブラリを追加します。 build.gradle dependencies { ... // Kotlin を使用するので ktx の方を指定します。 androidTestImplementation 'androidx.test:core-ktx:1.4.0' androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3' androidTestImplementation 'androidx.test:rules:1.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' } テストの作成 最初に app > src > andriodTest > java > パッケージ名 配下に LoginActivityTest というファイル(クラス)を作成しておきます。 アクティビティの開始と終了 作成したクラスに対して ActivityScenarioRule を追加します。UI テストでは Activity を開始したり終了したりする必要がありますが、ActivityScenarioRule を使用すると、これらの処理を自動的に行ってくれます(参考)。 LoginActivityTest.kt package com.example.uitestsample import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class LoginActivityTest { @get:Rule var activityScenarioRule = activityScenarioRule<LoginActivity>() @Test fun loginActivityTest() { ... } } Espresso における UI テストの基本 onView(withId(R.id.my_view)) // R.id.my_view を取得 .perform(click()) // ビューをクリック .check(matches(isDisplayed())) // ビューが表示されていることを検査 UI テストは主に以下のような3つの操作を組み合わせて行います。 onView() で対象となるビューを取得 allOf() を使って複数の条件を指定することも可能 ID 指定以外にもビュークラスの指定や ◯◯ の子要素など様々な条件設定が可能 perform() でビューの操作を実行 クリック以外にもテキストの入力やスワイプなど様々な操作が可能 check() でビューを検証 表示確認以外にもビューの存在チェックや表示テキストの確認などが可能 not() を使うことで条件を反転させることが可能 注意メッセージをテストする ユーザー名を入力する欄に何も入力せずログインボタンを押すと「ユーザー名を入力してください」というメッセージが表示されます。このメッセージが正しく表示されることをテストします。 LoginActivityTest.kt package com.example.uitestsample import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import org.hamcrest.Matchers.* import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class LoginActivityTest { @get:Rule var activityScenarioRule = activityScenarioRule<LoginActivity>() @Test fun loginActivityTest() { // メッセージが表示されていないことを確認。 // doesNotExist() は存在しないことを確認するため意味が異なる。 val noUserNameMessage = onView(withId(R.id.no_user_name_message)) noUserNameMessage.check(matches(not(isDisplayed()))) // ログインボタンを押下。 val loginButton = onView(withId(R.id.login_button)) loginButton.perform(click()) // EditText に何も入力せずログインボタンを押したとき // メッセージが正しく表示されることを確認。 noUserNameMessage.check( matches( allOf( isDisplayed(), withText("ユーザー名を入力してください") ) ) ) } } この状態で一度テストを実行してみると、成功することが確認できるかと思います。 なお、UI テストを実行するときは、端末の設定でアニメーションをオフにしておきます(参考)。 「ログイン中」が表示されていることを確認 ユーザー名を入力してログインボタンを押すと、ログイン中を示すビュー(ProgressBar + TextView)が表示されます。このビューが表示されていることを確認します。 LoginActivityTest.kt package com.example.uitestsample import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import org.hamcrest.Matchers.* import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class LoginActivityTest { @get:Rule var activityScenarioRule = activityScenarioRule<LoginActivity>() @Test fun loginActivityTest() { // *** ここまで省略 *** noUserNameMessage.check(matches(withText("ユーザー名を入力してください"))) // EditText にユーザー名を入れてログインボタンをクリック。 val userName = "福沢諭吉" onView(withId(R.id.user_name_edit_text)).perform(replaceText(userName)) loginButton.perform(click()) // 「ログイン中」が表示されていることを確認。 onView(withId(R.id.now_connecting_message)).check(matches(isDisplayed())) } } ここでは単純に LinearLayout R.id.now_connecting_message が表示されていることを確認しています。 ログインが完了するのを待ち合わせる 最後に、ログイン後「ようこそ◯◯さん」と表示されることをテストします。 ログインには少し時間がかかる(ここでは3秒)ので、ログインが完了するのを待ち合わせる必要があります。処理を待ち合わせる方法はいくつかあるのですが、今回は UI Automator の wait() を使用します。 wait() は指定した条件が満たされるまで処理を待機してくれます。今回は「ログイン後のメッセージビューが表示させる」ことを条件に処理を待機させます。 wait() メソッドは UI Automator フレームワークの UiDevice クラスに定義されているため、setUp() で UiDevice インスタンスを取得しておきます。 LoginActivityTest.kt package com.example.uitestsample import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.replaceText import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.ext.junit.rules.activityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until import org.hamcrest.Matchers.* import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @LargeTest class LoginActivityTest { @get:Rule var activityScenarioRule = activityScenarioRule<LoginActivity>() private lateinit var device: UiDevice @Before fun setUp() { // UiDevice インスタンスを取得。 device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) } @Test fun loginActivityTest() { // *** ここまで省略 *** onView(withId(R.id.now_connecting_message)).check(matches(isDisplayed())) // ログインに時間がかかるため R.id.welcome_text が表示されるまで待機。 val cond = Until.hasObject( By.res( "com.example.uitestsample", "welcome_text" ) ) val success = device.wait(cond, 5000L) // 指定した条件が満たされていることを確認。 assertThat(success, `is`(true)) // ログイン後のメッセージが正しいことを確認。 onView(withId(R.id.welcome_text)).check( matches(withText("ようこそ${userName}さん")) ) } } 待機条件の指定には Until.hasObject() を使います。これで「対象のオブジェクトが見つかること」という条件を作ります。また、対象となるオブジェクトの指定には By.res() を使います。第1引数にパッケージ名、第2引数にリソース名(R.id.my_text であれば my_text)を指定します。 作成した条件を wait() の第1引数で指定し、タイムアウトの時間を第2引数に指定します。タイムアウトまでに条件が満たされれば true が返されるので、戻り値が true であることを assertThat() で確認しています。 これでテストを実行すると成功するかと思います。 今回の実装ではログインに3秒かかるように設定しているため、タイムアウトの時間を1秒などに変更するとテストが失敗して、wait() が正確に機能していることが確認できます。 最後に こちらで LoginActivityTest 全体のコードが見れますので参考までに置いておきます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む