草庐IT

android - 从 IDE 运行测试有效,但不能从命令行运行

coder 2023-11-27 原文

我编写过单元测试、仪器测试和 Espresso 测试。我还使用 Android Test Orchestrator 运行它们以获得清晰的应用程序状态(对于 Espresso 测试很重要)。当我从 Android Studio 运行这些测试时,一切正常。但是当我尝试使用命令行时,我收到了我无法真正理解的错误。

当我尝试时:

./gradlew connectedAndroidTest or connectedDebugAndroidTest

我收到:

Instrumentation run failed due to 'java.lang.IllegalStateException'
com.android.builder.testing.ConnectedDevice > No tests found.[SM-J106H - 
6.0.1] FAILED 
No tests found. This usually means that your test classes are not in the 
form that your test runner expects (e.g. don't inherit from TestCase or lack 
@Test annotations).

当然,我所有的测试都带有@Test 注释。

当我尝试

adb shell am instrument -w my.package/android.test.InstrumentationTestRunner

我收到了

INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: 
ComponentInfo{mypackage/myCustomRunner}
INSTRUMENTATION_STATUS_CODE: -1

我使用 CustomTestRunner,但错误保持不变。

当我尝试

 adb shell 'CLASSPATH=$(pm path android.support.test.services) app_process / 
 \
 android.support.test.services.shellexecutor.ShellMain am instrument -w -e \
 targetInstrumentation 
 mypackage/myTestRunner \
 android.support.test.orchestrator/.AndroidTestOrchestrator'

那么输出等于:

Time: 0

OK (0 tests)

有人可以向我解释我做错了什么吗?我真的不明白为什么命令行没有任何作用,但在 Android Studio 中一切都运行良好。

/编辑

我的自定义运行器:

public final class CustomTestRunner extends AndroidJUnitRunner {

private static final String TAG = "CustomTestRunner";

@Override
public void onStart() {

    try {
        TestListener.getInstance().testRunStarted();
    } catch (Exception e) {
        e.printStackTrace();
    }

    runOnMainSync(new Runnable() {
        @Override
        public void run() {
            Context app = CustomTestRunner.this.getTargetContext().getApplicationContext();

            CustomTestRunner.this.disableAnimations(app);
        }
    });

    ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(new ActivityLifecycleCallback() {
        @Override public void onActivityLifecycleChanged(Activity activity, Stage stage) {
            if (stage == Stage.PRE_ON_CREATE) {
                activity.getWindow().addFlags(FLAG_DISMISS_KEYGUARD | FLAG_TURN_SCREEN_ON | FLAG_KEEP_SCREEN_ON);
            }
        }
    });

    RxJavaPlugins.setIoSchedulerHandler(new Function<Scheduler, Scheduler>() {
        @Override
        public Scheduler apply(Scheduler scheduler) throws Exception {
            return Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    });

    RxJavaPlugins.setComputationSchedulerHandler(new Function<Scheduler, Scheduler>() {
        @Override
        public Scheduler apply(Scheduler scheduler) throws Exception {
            return Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    });

    RxJavaPlugins.setNewThreadSchedulerHandler(new Function<Scheduler, Scheduler>() {
        @Override
        public Scheduler apply(Scheduler scheduler) throws Exception {
            return Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    });

    super.onStart();
}


@Override
public void finish(int resultCode, Bundle results) {
    try {
        TestListener.getInstance().testRunFinished();
    } catch (Exception e) {
        e.printStackTrace();
    }

    super.finish(resultCode, results);
    enableAnimations(getContext());
}

private void disableAnimations(Context context) {
    int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE);
    if (permStatus == PackageManager.PERMISSION_GRANTED) {
        setSystemAnimationsScale(0.0f);
    }
}

private void enableAnimations(Context context) {
    int permStatus = context.checkCallingOrSelfPermission(Manifest.permission.SET_ANIMATION_SCALE);
    if (permStatus == PackageManager.PERMISSION_GRANTED) {
        setSystemAnimationsScale(1.0f);
    }
}

private void setSystemAnimationsScale(float animationScale) {
    try {
        Class<?> windowManagerStubClazz = Class.forName("android.view.IWindowManager$Stub");
        Method asInterface = windowManagerStubClazz.getDeclaredMethod("asInterface", IBinder.class);
        Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
        Method getService = serviceManagerClazz.getDeclaredMethod("getService", String.class);
        Class<?> windowManagerClazz = Class.forName("android.view.IWindowManager");
        Method setAnimationScales = windowManagerClazz.getDeclaredMethod("setAnimationScales", float[].class);
        Method getAnimationScales = windowManagerClazz.getDeclaredMethod("getAnimationScales");

        IBinder windowManagerBinder = (IBinder) getService.invoke(null, "window");
        Object windowManagerObj = asInterface.invoke(null, windowManagerBinder);
        float[] currentScales = (float[]) getAnimationScales.invoke(windowManagerObj);
        for (int i = 0; i < currentScales.length; i++) {
            currentScales[i] = animationScale;
        }
        setAnimationScales.invoke(windowManagerObj, new Object[]{currentScales});
        Log.d(TAG, "Changed permissions of animations");
    } catch (Exception e) {
        Log.e(TAG, "Could not change animation scale to " + animationScale + " :'(");
    }
}
}

那是我的一个 Espresso 测试类(可见 RecyclerView 列表中的一个项目的 DetailView)

@RunWith(AndroidJUnit4.class)
public class DetailActivityTest {

private IdlingResource mInitialInformationIdlingResource;

@Before
public void setUp() throws UiObjectNotFoundException, InterruptedException {
    SetupHelper.setUp();

    File tempRealmFile = new File(InstrumentationRegistry.getTargetContext().getFilesDir(), PRODUCT_REALM_DB_FILE_NAME);

    if(tempRealmFile.length() <= 8192 && CustomAssertion.doesViewExist(R.id.countries)) {

        onView(withId(R.id.countries))
                .check(matches(isDisplayed()));
        onData(anything()).inAdapterView(withId(R.id.countries)).atPosition(3).perform(click());

        mInitialInformationIdlingResource = new InitialInformationIdlingResource();
        IdlingRegistry.getInstance().register(mInitialInformationIdlingResource);

        Espresso.onView(withText("OK"))
                .check(matches(isDisplayed()))
                .perform(click());
    }
}

@Test
public void ensureDetailViewWorks() throws UiObjectNotFoundException {
    SetupHelper.checkForDialogs();

    onView(withId(R.id.show_filter_results)).perform(scrollTo());

    onView(withId(R.id.show_filter_results))
            .check(matches(isDisplayed())).perform(scrollTo(), click());

    onView(withId(R.id.resultList)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
    onView(withId(R.id.main_container)).check(matches(isDisplayed()));
    onView(withId(R.id.detail_item_icon)).check(matches(isDisplayed()));
}

我在 build.gradle 中的构建类型

buildTypes {

    debug {
        debuggable true
        minifyEnabled false
        versionNameSuffix "-debug"
        manifestPlaceholders = [HOCKEYAPP_APP_ID: ""]
        testCoverageEnabled true
    }

    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
        versionNameSuffix "-release"
        manifestPlaceholders = [HOCKEYAPP_APP_ID: ""]
    }
}

最佳答案

查看您的设备/模拟器上的日志。甚至在测试开始之前,应用程序/测试代码中的某些内容就崩溃了。 “未找到测试。这通常意味着您的测试类不是您的测试运行程序所期望的形式。”对你完全没有帮助 =)

关于android - 从 IDE 运行测试有效,但不能从命令行运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50647307/

有关android - 从 IDE 运行测试有效,但不能从命令行运行的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  4. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  5. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  6. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  7. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  8. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  9. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  10. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

随机推荐