1
votes

This question is related to the previous ones: Codename One - Test Recorder: execute a test on a real device and Codename One - tests.dat file needed when using build.unitTest=1

My "test-for-ios-device" and "test-for-android-device" ant tasks produces IPAs and APKs that don't run any tests (actually the build server generates a .bin file that I rename to .ipa). Instead my tests work correctly in the Codename One Simulator. The tests are not trivial and all the logs plus one screenshot are sent to me by e-mail automatically during the test (using the Simulator), and I receive the report by e-mail without problems. Instead on real devices nothing happens.

I report the build.xml (I removed some irrilevant tasks in this copy) and the logs of Samsung Galaxy S6 and 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>

Samsung Galaxy S6 (only the relevant part of the log):

-----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

Note that LoginPageTest is public and without any constructor defined by me.

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
2

2 Answers

1
votes

I just sent a test build for iOS and got back a proper IPA.

enter image description here

I sent it by going to the files section of netbeans expanding the build.xml file and selecting the target then clicking "run target":

enter image description here

I even got the "included source" which lets me debug the output of the unit tests.

I suggest checking that the unit tests get packaged properly into the unit test jar with the app. This is my test for iOS device target which looks identical to yours:

<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>

This is my compile-tests target:

<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>
0
votes

Thank you Shai. After tons of trials to try to discover the reason of the issue that I reported, I finally found a "solution", that is run test-for-ios-device and test-for-android-device on Windows 8 instead of Linux Mint 18.2.

Ok, it's not a real "solution", but the only way that I found. On a Windows virtual machine and on a Linux virtual machine I have exactly the same version of jdk, the same version of Netbeans and of its plugins, the same project with the same build.xml and the same code. But if I run test-for-ios-device and test-for-android-device on Linux I get unusable apk and ipa from your build server, instead if I run them on Windows the result is fine.

Note that this isn't always true: this issue is not repeatable for all projects, that means that sometimes running test-for-ios-device and test-for-android-device on Linux works fine.