代号一 - test-for-ios-device 和 test-for-android-device 蚂蚁任务

Posted

技术标签:

【中文标题】代号一 - test-for-ios-device 和 test-for-android-device 蚂蚁任务【英文标题】:Codename One - test-for-ios-device and test-for-android-device ant tasks 【发布时间】:2017-12-08 13:51:41 【问题描述】:

这个问题和前面的问题有关:Codename One - Test Recorder: execute a test on a real device和Codename One - tests.dat file needed when using build.unitTest=1

我的“test-for-ios-device”和“test-for-android-device”ant 任务会生成不运行任何测试的 IPA 和 APK(实际上,构建服务器会生成一个 .bin 文件,我将其重命名为.ipa)。相反,我的测试在 Codename One 模拟器中正常工作。测试并非微不足道,所有日志和一张屏幕截图都会在测试期间通过电子邮件自动发送给我(使用模拟器),我通过电子邮件收到报告没有问题。相反,在真实设备上什么都不会发生。

我报告了build.xml(我在这个副本中删除了一些不相关的任务)以及三星Galaxy S6和iPhone8的日志。

<?xml version="1.0" encoding="UTF-8"?>
    <!--build_version=3.7-->
    <!-- 
    This build script was generated by Codename One to build native mobile applications using Java.
    To learn more about Codename One go to https://www.codenameone.com/
    -->

    <project name="Myapp" default="default" basedir=".">
    <description>Builds, tests, and runs the project Myapp.</description>
    <import file="nbproject/build-impl.xml"/>
    <property file="codenameone_settings.properties"/>
    <property name="automated" value="false" />
    <taskdef name="codeNameOne" classname="com.codename1.build.client.CodeNameOneBuildTask" classpath="CodeNameOneBuildClient.jar"/>
    <taskdef name="prepareTests" classname="com.codename1.build.client.PrepareTestsTask" classpath="CodeNameOneBuildClient.jar"/>
    <taskdef name="installLibs" classname="com.codename1.build.client.InstallLibsTask" classpath="CodeNameOneBuildClient.jar"/>
    <taskdef name="verifyDir" classname="com.codename1.build.client.VerifyDir" classpath="CodeNameOneBuildClient.jar"/>
    <taskdef name="generateGuiSources" classname="com.codename1.build.client.GenerateGuiSources" classpath="CodeNameOneBuildClient.jar"/>
    <taskdef name="initOfflineBuilder" classname="com.codename1.build.client.InitOfflineBuilder" classpath="CodeNameOneBuildClient.jar"/>

    <target depends="init,compile,jar" name="compile-test">
        <mkdir dir="$build.test.classes.dir" />
        <mkdir dir="$test.src.dir" />
        <javac destdir="$build.test.classes.dir"
            encoding="$source.encoding"
            source="1.8"
            target="1.8"
            bootclasspath="CLDC11.jar" excludes="$excludes"
            classpath="$javac.classpath:$build.classes.dir">
            <src path="$test.src.dir"/>
        </javac>        
        <prepareTests classesDir="$build.classes.dir" testClassesDir="$build.test.classes.dir" seJar="JavaSE.jar" metaDataFile="$build.test.classes.dir/tests.dat" />
        <jar jarfile="dist/unitTests.jar">
            <fileset dir="$build.classes.dir"/>
            <fileset dir="$build.test.classes.dir"/>
            <fileset dir="lib/impl/cls"/>
        </jar>
    </target>

    <target depends="compile-test" name="-do-test-run">        
        <!-- JavaSE.jar is added here since the test execution might fail otherwise for a pre-existing project -->
        <java classpath="dist/unitTests.jar:$javac.test.classpath:$file.reference.JavaSE.jar" classname="com.codename1.impl.javase.TestRunner" fork="true">
            <arg value="$codename1.packageName.$codename1.mainName" />
        </java>
    </target>

    <target depends="-do-test-run" description="Run unit tests." name="test"/>

    <target name="-pre-compile">
        <echo>Compile is forcing compliance to the supported API's/features for maximum device compatibility. This allows smaller
        code size and wider device support</echo>
        <mkdir dir="build/tmp"/>
        <javac destdir="build/tmp"
            encoding="$source.encoding"
            source="1.8"
            target="1.8"
            bootclasspath="lib/CLDC11.jar" excludes="$excludes"
            classpath="$javac.classpath:$build.classes.dir">
            <src path="$src.dir"/>
        </javac>        
    </target>

    <target name="-post-compile">
        <delete>
            <fileset dir="$build.classes.dir" includes="**/package-info.class"/>
        </delete>
        <delete>
            <fileset dir="$build.classes.dir" includes="**/package-info.class"/>
        </delete>
        <delete>
            <fileset dir="$build.classes.dir" includes="**/Thumbs.db"/>
        </delete>
    </target>

    <target name="build-for-ios-device" depends="clean,copy-ios-override,copy-libs,jar,clean-override">
        <codeNameOne 
            jarFile="$dist.jar"
            displayName="$codename1.displayName"
            packageName = "$codename1.packageName"
            mainClassName = "$codename1.mainName"
            version="$codename1.version"
            icon="$codename1.icon"
            vendor="$codename1.vendor"
            subtitle="$codename1.secondaryTitle"

            targetType="iphone"
            certificate="$codename1.ios.debug.certificate"
            certPassword="$codename1.ios.debug.certificatePassword"
            provisioningProfile="$codename1.ios.debug.provision"
            appid="$codename1.ios.appid"
            automated="$automated"
            />
    </target>

    <target name="test-for-ios-device" depends="clean,copy-ios-override,copy-libs,compile-test,clean-override">
        <codeNameOne 
            jarFile="dist/unitTests.jar"
            displayName="$codename1.displayName"
            packageName = "$codename1.packageName"
            mainClassName = "$codename1.mainName"
            version="$codename1.version"
            icon="$codename1.icon"
            vendor="$codename1.vendor"
            subtitle="$codename1.secondaryTitle"
            buildArgs="build.unitTest=1"
            targetType="iphone"
            certificate="$codename1.ios.debug.certificate"
            certPassword="$codename1.ios.debug.certificatePassword"
            provisioningProfile="$codename1.ios.debug.provision"
            appid="$codename1.ios.appid"
            automated="$automated"
            />
    </target>

    <target name="test-for-android-device" depends="clean,copy-android-override,copy-libs,compile-test,clean-override">
        <codeNameOne 
            jarFile="dist/unitTests.jar"
            displayName="$codename1.displayName"
            packageName = "$codename1.packageName"
            mainClassName = "$codename1.mainName"
            version="$codename1.version"
            icon="$codename1.icon"
            vendor="$codename1.vendor"
            subtitle="$codename1.secondaryTitle"
            buildArgs="build.unitTest=1"
            targetType="android"
            keystoreAlias="$codename1.android.keystoreAlias"
            keystore="$codename1.android.keystore"
            certPassword="$codename1.android.keystorePassword"
            automated="$automated"
            />
    </target>


    <target name="build-for-ios-device-release" depends="clean,copy-ios-override,copy-libs,jar,clean-override">
        <codeNameOne 
            jarFile="$dist.jar"
            displayName="$codename1.displayName"
            packageName = "$codename1.packageName"
            mainClassName = "$codename1.mainName"
            version="$codename1.version"
            icon="$codename1.icon"
            vendor="$codename1.vendor"
            subtitle="$codename1.secondaryTitle"
            appStoreBuild="true"
            production="true"
            targetType="iphone"
            certificate="$codename1.ios.release.certificate"
            certPassword="$codename1.ios.release.certificatePassword"
            provisioningProfile="$codename1.ios.release.provision"
            appid="$codename1.ios.appid"
            automated="$automated"
            />
    </target>

    <target name="copy-libs" depends="init">
        <copy todir="$build.classes.dir">
            <fileset dir="lib/impl/cls" />
        </copy>
    </target>

    <target name="copy-android-override">
        <mkdir dir="$build.classes.dir" />
        <mkdir dir="override" />
        <copy todir="$build.classes.dir">
            <fileset dir="override" includes="**/*_android.ovr"/>
            <fileset dir="override" includes="**/*_android-phone.ovr"/>
            <fileset dir="override" includes="**/*_android-tab.ovr"/>
            <fileset dir="override" includes="**/*_phone.ovr"/>
            <fileset dir="override" includes="**/*_tablet.ovr"/>
        </copy>
        <copy todir="$build.classes.dir">
            <fileset dir="native/android" includes="**/*"/>
            <fileset dir="lib/impl/native/android" includes="**/*"/>
        </copy>
    </target>

    <target name="copy-ios-override">
        <mkdir dir="$build.classes.dir" />
        <mkdir dir="override" />
        <copy todir="$build.classes.dir">
            <fileset dir="override" includes="**/*_ios.ovr"/>
            <fileset dir="override" includes="**/*_iphone.ovr"/>
            <fileset dir="override" includes="**/*_ipad.ovr"/>
            <fileset dir="override" includes="**/*_phone.ovr"/>
            <fileset dir="override" includes="**/*_tablet.ovr"/>
        </copy>
        <copy todir="$build.classes.dir">
            <fileset dir="native/ios" includes="**/*"/>
            <fileset dir="lib/impl/native/ios" includes="**/*"/>
        </copy>
    </target>


    <target name="clean-override">
        <delete>
            <fileset dir="$build.classes.dir" includes="**/*.ovr"/>
            <fileset dir="$build.classes.dir" includes="**/*.java"/>
            <fileset dir="$build.classes.dir" includes="**/*.m"/>
            <fileset dir="$build.classes.dir" includes="**/*.h"/>
        </delete>
    </target>

    <target name="build-for-android-device" depends="clean,copy-android-override,copy-libs,jar,clean-override">
        <codeNameOne 
            jarFile="$dist.jar"
            displayName="$codename1.displayName"
            packageName = "$codename1.packageName"
            mainClassName = "$codename1.mainName"
            version="$codename1.version"
            icon="$codename1.icon"
            vendor="$codename1.vendor"
            subtitle="$codename1.secondaryTitle"

            targetType="android"
            keystoreAlias="$codename1.android.keystoreAlias"
            keystore="$codename1.android.keystore"
            certPassword="$codename1.android.keystorePassword"
            automated="$automated"
            />
    </target> 

    <target name="-pre-init">
        <property name="application.args" value="$codename1.packageName.$codename1.mainName"/>
        <property name="javac.source" value="1.8" />
        <property name="javac.target" value="1.8" />
        <mkdir dir="native/javase" />
        <mkdir dir="native/android" />
        <mkdir dir="native/internal_tmp" />
        <mkdir dir="native/ios" />
        <mkdir dir="native/j2me" />
        <mkdir dir="native/rim" />
        <mkdir dir="native/win" />
        <mkdir dir="native/javascript" />
        <mkdir dir="lib/impl/cls" />
        <mkdir dir="lib/impl/stubs" />
        <mkdir dir="lib/impl/native" />
        <mkdir dir="lib/impl/native/android" />
        <mkdir dir="lib/impl/native/ios" />
        <mkdir dir="lib/impl/native/j2me" />
        <mkdir dir="lib/impl/native/rim" />
        <mkdir dir="lib/impl/native/win" />
        <mkdir dir="lib/impl/native/javascript" />
        <installLibs lib="lib" dest="lib/impl" />
        <generateGuiSources srcDir="src" encoding="UTF-8" guiDir="res/guibuilder"  />
    </target>

    <target name="-post-jar">
        <mkdir dir="native/javase" />
        <mkdir dir="native/internal_tmp" />
        <mkdir dir="lib/impl/native/javase" />
        <javac destdir="native/internal_tmp"
            encoding="$source.encoding"
            source="1.8"
            target="1.8"
            bootclasspath="CLDC11.jar" excludes="$excludes"
            classpath="$javac.classpath:$build.classes.dir">
            <src path="native/javase"/>
            <src path="lib/impl/native/javase"/>
        </javac>        
    </target>

    <target name="-post-clean" depends="refresh-libs-impl">
    </target>

    <target name="refresh-libs" depends="refresh-libs-impl,jar">
    </target>

    <target name="refresh-libs-impl">
        <delete dir="lib/impl" />
        <installLibs lib="lib" dest="lib/impl" />        
    </target>

</project>

三星 Galaxy S6(仅日志的相关部分):

-----STARTING TESTS-----
>   12-08 13:19:05.751 D/Myapp( 6834): [EDT] 0:0:0,10 - Failed to create instance of cool.myapp.app.tests.LoginPageTest
>   12-08 13:19:05.751 D/Myapp( 6834): [EDT] 0:0:0,10 - Verify the class is public and doesn't have a specialized constructor
>   12-08 13:19:05.751 D/Myapp( 6834): [EDT] 0:0:0,11 - Exception: java.lang.ClassNotFoundException - cool.myapp.app.tests.LoginPageTest
>   12-08 13:19:05.751 W/System.err( 6834): java.lang.ClassNotFoundException: cool.myapp.app.tests.LoginPageTest

请注意,LoginPageTest 是公开的,没有我定义的任何构造函数。

iPhone 8:

> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(libAccessibility.dylib)[35170] <Notice>: Retrieving resting unlock: 0
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(FrontBoardServices)[35170] <Notice>: [FBDisplayManager=0x1d404b1f0] silently connecting <FBSDisplayConfiguration: 0x1d4177e80; Main; mode: "375x667@2x 60Hz p3"> 
>     CADisplay.name = LCD;
>     CADisplay.deviceName = primary;
>     CADisplay.seed = 2;
>     tags = 0;
>     currentMode = <FBSDisplayMode: 0x1d4268140; 375x667@2x (750x1334/2) 60Hz p3>;
>     safeOverscanRatio = 0.89999997615814209, 0.89999997615814209;
>     nativeCenter = 375, 667;
>     pixelSize = 750, 1334;
>     bounds = 0, 0, 375, 667;
>     CADisplay = <CADisplay:LCD primary>;
> 
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(UserNotifications)[35170] <Notice>: [cool.myapp.app] Setting badge number to 0
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(UserNotifications)[35170] <Notice>: [cool.myapp.app] Set badge number [ hasCompletionHandler: 0 hasError: 0 ]
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(HangTracer)[35170] <Notice>: refreshPreferences: HangTracerEnabled: 0
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(HangTracer)[35170] <Notice>: refreshPreferences: HangTracerDuration: 500
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(HangTracer)[35170] <Notice>: refreshPreferences: ActivationLoggingEnabled: 0 ActivationLoggingTaskedOffByDA:0
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(UserNotifications)[35170] <Notice>: [cool.myapp.app] Setting badge number to 0
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(UserNotifications)[35170] <Notice>: [cool.myapp.app] Set badge number [ hasCompletionHandler: 0 hasError: 0 ]
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(CoreGraphics)[35170] <Error>: CGContextSetAllowsAntialiasing: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
> Dec  8 13:26:35 iPhone CodenameOneUnitTestExecutor(UIAccessibility)[35170] <Notice>: loading ax info now. wasCoalesced: 1
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC Enabling TLS [1:0x1d4366840]
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TCP Conn Start [1:0x1d4366840]
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Task <1F77BFCA-1D0F-42ED-BAE8-4E0A54D579F7>.<0> setting up Connection 1
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Sending CFNA PAC query
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Received CFNA PAC response
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TCP Conn Connected [1:0x1d4366840]: Err(16)
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TCP Conn Event [1:0x1d4366840]: 1
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC Enabling TLS [1:0x1d4366840]
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 1, Pending(0)
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(UIAccessibility)[35170] <Notice>: loading ax info now. wasCoalesced: 1
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 2, Pending(0)
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(libboringssl.dylib)[35170] <Error>: Function boringssl_context_get_peer_sct_list: line 1754 received sct extension length is less than sct data length
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 11, Pending(0)
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 12, Pending(0)
> Dec  8 13:26:36 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 14, Pending(0)
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Trust Result [1:0x1d4366840]: 0
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Event [1:0x1d4366840]: 20, Pending(0)
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TCP Conn Event [1:0x1d4366840]: 8
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: TIC TLS Handshake Complete [1:0x1d4366840]
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Task <1F77BFCA-1D0F-42ED-BAE8-4E0A54D579F7>.<0> now using Connection 1
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Task <1F77BFCA-1D0F-42ED-BAE8-4E0A54D579F7>.<0> sent request, body N
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Task <1F77BFCA-1D0F-42ED-BAE8-4E0A54D579F7>.<0> received response, status 200 content K
> Dec  8 13:26:37 iPhone CodenameOneUnitTestExecutor(CFNetwork)[35170] <Notice>: Task <1F77BFCA-1D0F-42ED-BAE8-4E0A54D579F7>.<0> response ended

【问题讨论】:

【参考方案1】:

我刚刚发送了一个 iOS 测试版本并取回了一个合适的 IPA。

我通过转到 netbeans 的文件部分来扩展 build.xml 文件并选择目标然后单击“运行目标”来发送它:

我什至得到了“包含的源”,它可以让我调试单元测试的输出。

我建议检查单元测试是否与应用程序一起正确打包到单元测试 jar 中。这是我对 iOS 设备目标的测试,看起来与您的相同:

<target name="test-for-ios-device" depends="clean,copy-ios-override,copy-libs,compile-test,clean-override">
    <codeNameOne 
        jarFile="dist/unitTests.jar"
        displayName="$codename1.displayName"
        packageName = "$codename1.packageName"
        mainClassName = "$codename1.mainName"
        version="$codename1.version"
        icon="$codename1.icon"
        vendor="$codename1.vendor"
        subtitle="$codename1.secondaryTitle"
        buildArgs="build.unitTest=1"
        targetType="iphone"
        certificate="$codename1.ios.debug.certificate"
        certPassword="$codename1.ios.debug.certificatePassword"
        provisioningProfile="$codename1.ios.debug.provision"
        appid="$codename1.ios.appid"
        automated="$automated"
        />
</target>

这是我的compile-tests 目标:

<target depends="init,compile,jar" name="compile-test">
    <mkdir dir="$build.test.classes.dir" />
    <mkdir dir="$test.src.dir" />
    <javac destdir="$build.test.classes.dir"
        encoding="$source.encoding"
        source="1.8"
        target="1.8"
        bootclasspath="CLDC11.jar" excludes="$excludes"
        classpath="$javac.classpath:$build.classes.dir">
        <src path="$test.src.dir"/>
    </javac>        
    <prepareTests classesDir="$build.classes.dir" testClassesDir="$build.test.classes.dir" seJar="JavaSE.jar" metaDataFile="$build.test.classes.dir/tests.dat" />
    <jar jarfile="dist/unitTests.jar">
        <fileset dir="$build.classes.dir"/>
        <fileset dir="$build.test.classes.dir"/>
        <fileset dir="lib/impl/cls"/>
    </jar>
</target>

【讨论】:

今天我还发现将 Linux 切换到 Windows 并不能解决问题(请参阅下面的答案),因为 test-for-android-device 只有在我没有生成工作 apk 的情况下才能为我工作安装了任何 Android 证书(让 Codename One 构建服务器每次都生成一个临时证书)。相反,如果我在我的机器上生成一个 Android 证书,那么测试 apk 就会损坏。这似乎是一种无意义的行为。我希望下一个 Codename One 4.0 将集成对设备测试的真正更好的支持,从而为我省去很多麻烦和浪费的时间。【参考方案2】:

谢谢你。经过大量试验试图找出我报告的问题的原因,我终于找到了一个“解决方案”,即在 Windows 8 而不是 Linux Mint 上运行 test-for-ios-device 和 test-for-android-device 18.2.

好吧,这不是一个真正的“解决方案”,而是我找到的唯一方法。在 Windows 虚拟机和 Linux 虚拟机上,我拥有完全相同版本的 jdk、相同版本的 Netbeans 及其插件、具有相同 build.xml 和相同代码的相同项目。但是如果我在 Linux 上运行 test-for-ios-device 和 test-for-android-device 我会从你的构建服务器中得到不可用的 apk 和 ipa,如果我在 Windows 上运行它们,结果就很好。

请注意,这并不总是正确的:此问题并非对所有项目都可重复,这意味着有时在 Linux 上运行 test-for-ios-device 和 test-for-android-device 可以正常工作。

【讨论】:

我猜您正尝试在设备中已安装的应用程序之上安装,并且您看到了冲突。您需要删除设备中占用该包名的应用程序,然后安装 APK。它没有坏。这对于我们通常测试的农场上的自动测试解决方案来说不是问题,因为设备总是“干净”的。 Widnows/Linux 与我们使用 Mac 无关。 如果您在查看设备日志的同时尝试安装损坏的 APK,控制台中会出现什么错误? 错误与我在问题中报告的相同。 apk 错误是 java.lang.ClassNotFoundException,如您在上面所读。 我认为我们需要重现这一点,我不确定为什么会发生这种情况。请提出问题,我们会尽力跟进。

以上是关于代号一 - test-for-ios-device 和 test-for-android-device 蚂蚁任务的主要内容,如果未能解决你的问题,请参考以下文章

代号一 IOS CaptureAudio

代号一构建失败

代号一 showNativePicker 未显示

代号一上传图片到S3存储桶权限

代号一 Android Sidemenu

代号一刷新表单