我用 android studio 创建了一个仪器测试,使用 Express Record Test。
流程:
-> 从 Activity_splash_screen 类开始。
-> 然后 LoginActivity.java 屏幕进入屏幕。
-> 在登录屏幕转到另一个要求 DDI、电话和用户 ID 的活动 (ValuesPeternActivity.java) 之后。
在 HomeActivity.java 中结束流程
1°测试填写登录名和密码字段;(成功)
2°点击下一个标题进入新屏幕;(成功)
3° 发生错误,因为它停在 txtDDI 字段中,这是第二个屏幕上的第一个字段。(错误)
如果我坚持反复执行,有时测试通过,有时甚至第一次屏幕测试都没有通过。我相信它表征了 express 和 thread 之间缺乏同步。
如何同步?
我发现了它,但我无法实现它。查看链接-> IdlingRegistry 和 Espresso 将等待资源
我看到一个视频,其中那个人正在做这个测试并且不需要任何测试。一定是因为androidx,只能!
错误的错误:
Started running tests
androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: Child at position 0 in parent Child at position 0 in parent view.getId() is <2131296889/br.com.cellsgroupleader:id/txtDDI>
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1366, height=406, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(wrapxwrap) gr=CENTER sim={adjust=pan} ty=APPLICATION fmt=TRANSLUCENT wanim=0x10302f9
fl=DIM_BEHIND FULLSCREEN ALT_FOCUSABLE_IM SPLIT_TOUCH HARDWARE_ACCELERATED}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1} |
+----->Space{id=16909413, res-name=titleDividerNoCustom, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@d7e62e0, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+---->FrameLayout{id=16908813, res-name=contentPanel, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@5ed645e, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
+------->Space{id=16909395, res-name=textSpacerNoTitle, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@550d2d1, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+------->AppCompatTextView{id=16908299, res-name=message, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@24ba136, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+------->Space{id=16909394, res-name=textSpacerNoButtons, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@b164837, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+---->FrameLayout{id=16908820, res-name=customPanel, visibility=VISIBLE, width=1254, height=294, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@83ecb0d, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+----->FrameLayout{id=16908331, res-name=custom, visibility=VISIBLE, width=1254, height=294, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@3fd30d3, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+---->ScrollView{id=16908766, res-name=buttonPanel, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@16fe74b, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}
|
+----->ButtonBarLayout{id=-1, visibility=VISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@d8ccbd4, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=4}
|
+------>AppCompatButton{id=16908315, res-name=button3, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@505917d, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+------>Space{id=16909328, res-name=spacer, visibility=INVISIBLE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@9613872, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
+------>AppCompatButton{id=16908314, res-name=button2, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@7c3f4c3, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+------>AppCompatButton{id=16908313, res-name=button1, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=true, is-selected=false, layout-params=android.widget.LinearLayout$LayoutParams@4d4d140, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, text=, input-type=0, ime-target=false, has-links=false}
|
+-->ViewStub{id=16908682, res-name=action_mode_bar_stub, visibility=GONE, width=0, height=0, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams@ddec879, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}
|
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1538)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:12)
at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:7)
at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:8)
at androidx.test.espresso.ViewInteraction.desugaredPerform(ViewInteraction.java:11)
at androidx.test.espresso.ViewInteraction.perform(ViewInteraction.java:4)
at br.com.cellsgroupleader.Activity_splash_screenTest.activity_splash_screenTest(Activity_splash_screenTest.java:111)
Tests ran to completion.
Express Record Test 生成的 Activity_splash_screen_Test
在这里我必须放置 editText.check (matches (withText (endsWith ("joseb@gmail.com"))))。
endWidth 帮助只取必要的东西,因为我在这里犯了一个错误。
package br.com.cellsgroupleader;
import android.content.*;
import android.view.*;
import androidx.test.espresso.*;
import androidx.test.filters.*;
import androidx.test.platform.app.*;
import androidx.test.rule.*;
import androidx.test.runner.*;
import org.hamcrest.Description;
import org.hamcrest.*;
import org.junit.*;
import org.junit.runner.*;
import static androidx.test.espresso.Espresso.*;
import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
import static androidx.test.espresso.action.ViewActions.*;
import static androidx.test.espresso.assertion.ViewAssertions.*;
import static androidx.test.espresso.matcher.ViewMatchers.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@LargeTest
@RunWith( AndroidJUnit4.class )
public class Activity_splash_screenTest{
@Rule
public ActivityTestRule < Activity_splash_screen > mActivityTestRule = new ActivityTestRule <>( Activity_splash_screen.class );
@Test
public void useAppContext( ){
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation( ).getTargetContext( );
assertEquals( "br.com.cellsgroupleader" , appContext.getPackageName( ) );
}
@Test
public void activity_splash_screenTest( ){
ViewInteraction textInputEditText = onView(
childAtPosition(
childAtPosition(
withId(R.id.email) ,
0 ) ,
0 ) );
textInputEditText.perform( scrollTo( ) , click( ) );
ViewInteraction textInputEditText2 = onView(
childAtPosition(
childAtPosition(
withId( R.id.email ) ,
0 ) ,
0 ) );
textInputEditText2.perform( scrollTo( ) , replaceText( "joseb@gmail.com" ) , closeSoftKeyboard( ) );
ViewInteraction textInputEditText3 = onView(
allOf( withText( "joseb@gmail.com" ) ,
childAtPosition(
childAtPosition(
withId( R.id.email ) ,
0 ) ,
0 ) ) );
textInputEditText3.perform( pressImeActionButton( ) );
ViewInteraction textInputEditText4 = onView(
childAtPosition(
childAtPosition(
withId( R.id.password ) ,
0 ) ,
0 ) );
textInputEditText4.perform( scrollTo( ) , replaceText( "123456" ) , closeSoftKeyboard( ) );
ViewInteraction textInputEditText5 = onView(
allOf( withText( "123456" ) ,
childAtPosition(
childAtPosition(
withId( R.id.password ) ,
0 ) ,
0 ) ) );
textInputEditText5.perform( pressImeActionButton( ) );
ViewInteraction editText = onView(
allOf( withText( "joseb@gmail.com" ) ,
withParent( withParent( withId( R.id.email ) ) ) ,
isDisplayed( ) ) );
editText.check( matches( withText(endsWith("joseb@gmail.com")) ) );
ViewInteraction editText2 = onView(
allOf( withText( "123456" ) ,
withParent( withParent( withId( R.id.password ) ) ) ,
isDisplayed( ) ) );
editText2.check( matches( withText(endsWith("123456")) ) );
ViewInteraction appCompatButton = onView(
allOf( withId( R.id.btnEnviarLogin ) , withText( "Entrar" ) ,
childAtPosition(
childAtPosition(
withClassName( is( "android.widget.LinearLayout" ) ) ,
4 ) ,
1 ) ) );
appCompatButton.perform( scrollTo( ) , click( ) );
ViewInteraction textInputEditText6 = onView(
childAtPosition(
childAtPosition(
withId( R.id.txtDDI ) ,
0 ) ,
0 ) );
textInputEditText6.perform( scrollTo( ) , replaceText( "+55" ) , closeSoftKeyboard( ) );
ViewInteraction textInputEditText7 = onView(
allOf( withText( "+55" ) ,
childAtPosition(
childAtPosition(
withId( R.id.txtDDI ) ,
0 ) ,
0 ) ) );
textInputEditText7.perform( pressImeActionButton( ) );
ViewInteraction textInputEditText14 = onView(
allOf( withText( "(48)96456-5896" ) ,
childAtPosition(
childAtPosition(
withId( R.id.txtfone ) ,
0 ) ,
0 ) ,
isDisplayed( ) ) );
textInputEditText14.perform( closeSoftKeyboard( ) );
ViewInteraction textInputEditText15 = onView(
allOf( withText( "(48)96456-5896" ) ,
childAtPosition(
childAtPosition(
withId( R.id.txtfone ) ,
0 ) ,
0 ) ) );
textInputEditText15.perform( pressImeActionButton( ) );
ViewInteraction textInputEditText16 = onView(
childAtPosition(
childAtPosition(
withId( R.id.txtcodigoID ) ,
0 ) ,
0 ) );
textInputEditText16.perform( scrollTo( ) , longClick( ) );
ViewInteraction linearLayout = onView(
allOf( withContentDescription( "Colar" ) ,
childAtPosition(
childAtPosition(
withClassName( is( "android.widget.RelativeLayout" ) ) ,
1 ) ,
0 ) ,
isDisplayed( ) ) );
linearLayout.perform( click( ) );
ViewInteraction textInputEditText17 = onView(
childAtPosition(
childAtPosition(
withId( R.id.txtcodigoID ) ,
0 ) ,
0 ) );
textInputEditText17.perform( scrollTo( ) , replaceText( "-MU7CLJOxn3s8iG7l9MS" ) , closeSoftKeyboard( ) );
ViewInteraction textInputEditText18 = onView(
allOf( withText( "-MU7CLJOxn3s8iG7l9MS" ) ,
childAtPosition(
childAtPosition(
withId( R.id.txtcodigoID ) ,
0 ) ,
0 ) ) );
textInputEditText18.perform( pressImeActionButton( ) );
ViewInteraction editText3 = onView(
allOf( withText( "+55" ) ,
withParent( withParent( withId( R.id.txtDDI ) ) ) ,
isDisplayed( ) ) );
editText3.check( matches( withText( "+55" ) ) );
ViewInteraction editText4 = onView(
allOf( withText( "(48)96456-5896" ) ,
withParent( withParent( withId( R.id.txtfone ) ) ) ,
isDisplayed( ) ) );
editText4.check( matches( withText( "(48)96456-5896" ) ) );
ViewInteraction editText5 = onView(
allOf( withText( "-MU7CLJOxn3s8iG7l9MS" ) ,
withParent( withParent( withId( R.id.txtcodigoID ) ) ) ,
isDisplayed( ) ) );
editText5.check( matches( withText( "-MU7CLJOxn3s8iG7l9MS" ) ) );
ViewInteraction appCompatButton2 = onView(
allOf( withId( R.id.txtAvancar ) , withText( "Avançar" ) ,
childAtPosition(
childAtPosition(
withClassName( is( "android.widget.ScrollView" ) ) ,
0 ) ,
6 ) ) );
appCompatButton2.perform( scrollTo( ) , click( ) );
}
private static Matcher < View > childAtPosition(
final Matcher < View > parentMatcher , final int position ){
return new TypeSafeMatcher < View >( ){
@Override
public void describeTo( Description description ){
description.appendText( "Child at position " + position + " in parent " );
parentMatcher.describeTo( description );
}
@Override
public boolean matchesSafely( View view ){
ViewParent parent = view.getParent( );
return parent instanceof ViewGroup && parentMatcher.matches( parent )
&& view.equals( ( ( ViewGroup ) parent ).getChildAt( position ) );
}
};
}
}
./gradle
plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
}
android {
signingConfigs {
release {
storeFile file('/home/fsp/Área de Trabalho/PRIVATE KEYS ANDROID/KEYS_ANDROID')
storePassword ''
keyAlias ''
keyPassword ''
}
debug {
storeFile file('/home/fsp/Área de Trabalho/PRIVATE KEYS ANDROID/KEYS_ANDROID')
storePassword ''
keyAlias ''
keyPassword ''
}
}
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "br.com.cellsgroupleader"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.release
}
testOptions {
unitTests.returnDefaultValues = true
}
useLibrary 'android.test.runner'
useLibrary 'android.test.base'
useLibrary 'android.test.mock'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
ndkVersion '21.3.6528147'
buildTypes {
release {
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.debug
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.preference:preference:1.1.1'
//noinspection GradleDependency
implementation 'androidx.navigation:navigation-fragment:2.3.2'
//noinspection GradleDependency
implementation 'androidx.navigation:navigation-ui:2.3.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.drawerlayout:drawerlayout:1.1.1'
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
//noinspection GradleDependency
implementation 'com.google.android.material:material:1.2.0-alpha02'
implementation 'com.google.firebase:firebase-auth:20.0.2'
implementation 'com.google.android.gms:play-services-auth:19.0.0'
implementation 'androidx.test.espresso:espresso-intents:3.4.0-alpha04'
androidTestImplementation 'androidx.test:rules:1.3.0'
//noinspection GradleDependency
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.13.2'
// Optional -- Robolectric environment
testImplementation 'androidx.test:core:1.3.0'
// Optional -- Mockito framework
testImplementation 'org.mockito:mockito-core:1.10.19'
// Core library
androidTestImplementation 'androidx.test:core:1.3.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
// Assertions
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.ext:truth:1.3.0'
androidTestImplementation 'com.google.truth:truth:1.0'
// Espresso dependencies
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-web:3.3.0'
androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.3.0'
//firebase
implementation 'com.google.firebase:firebase-functions:19.2.0'
implementation 'com.google.firebase:firebase-storage:19.2.1'
implementation platform('com.google.firebase:firebase-bom:26.3.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-database:19.6.0'
implementation 'com.google.firebase:firebase-auth:20.0.2'
implementation 'com.github.prolificinteractive:material-calendarview:1.4.3'
//glide
implementation 'com.github.bumptech.glide:glide:4.8.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
//noinspection GradleDependency
implementation 'androidx.navigation:navigation-dynamic-features-fragment:2.3.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}