【问题标题】:Testing iPhone apps effectively with release builds使用发布版本有效地测试 iPhone 应用程序
【发布时间】:2010-10-04 13:46:27
【问题描述】:

我们有一个应用在来自 App Store 的 armv6 iOS 设备上崩溃。 armv7 iOS 设备运行得很好。当应用程序作为调试程序构建和测试时,它在 armv6armv7 上运行得很好。在日志中,当它试图从库中构造一个对象时,我得到了EXC_BAD_INSTRUCTION。崩溃似乎是发布版本中的链接错误,因为我有几个来自three20的静态库。一开始我以为是iOS版本的问题,现在看来是“胖二进制”的问题。

ad-hoc 是模拟 App Store 进行测试的最佳方式吗?在设备上测试发布版本的最佳方法是什么?在 release 版本中测试与不同设备的链接的最佳方法是什么?

【问题讨论】:

    标签: iphone objective-c crash linker


    【解决方案1】:

    我找不到 iOS 兼容性测试实验室的参考资料,但我听说目前可用。如果我能找到这个资源,我会更新我的回复。

    同时,您可以在这里找到 UI 自动化测试建议:Automated testing for iPhone

    很遗憾,您必须找到 3g iPhone 才能验证 arm6 的兼容性。我希望您只需询问您认识的每个拥有新 iPhone 的人,就能轻松找到一款。他们可能像我一样把旧手机放在抽屉里。我用我的进行测试。

    如果您可以证明一个复杂的解决方案是合理的,您可以将旧 iPhone 永久连接到 mac mini,并使用上面引用的使用 Hudson 或 CruiseControl 的 UI 测试框架来驱动 UI。如果您可以进行前期投资,这将是最可靠且最省时的方法。

    【讨论】:

      【解决方案2】:

      您可以使用 codesign 命令行工具更改已构建应用的代码签名权限。构建你的分发目标后,应用文件将具有“分发”权限;您需要将其更改为 development 权限。更改后,您可以在开发设备上安装构建并进行测试。

      要查看应用签名的详细转储:

      $ codesign -d -vv MyApp.app/MyApp
      

      要更改协同设计权限:

      $ codesign -f -s "My iPhone Developer Name" -vv MyApp.app/MyApp
      

      您可能需要创建一个环境变量来获取 codesign_allocate 的正确版本:

      $ export CODESIGN_ALLOCATE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
      

      我在 Craig Hockenberry 的博客上找到了这些说明,其中包含有关此过程的许多其他信息:http://furbo.org/2008/11/12/the-final-test/

      【讨论】:

        【解决方案3】:

        我能够使用临时分发对其进行测试。

        【讨论】:

        • 使用最新的 Xcode 非常简单:存档,单击分发并选择 Ad Hoc,转到 Provisioning Portal 并创建并下载 Ad Hoc .mobileprovision。最后,将 app 和 .mobileprovision 拖入 iTunes。
        【解决方案4】:

        我使用 ANT 创建版本,利用 xcodebuild 命令行实用程序。蚂蚁目标看起来像这样:

         <target name="build-adhoc">
                <echo>Running XCODE compiler</echo>
                <exec executable="xcodebuild" failonerror="true" vmlauncher="false" dir="${connect_src}">
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="myappname" />
                    <arg value="-configuration"/>
                    <arg value="AdHoc"/>
                    <arg value="SYMROOT=${export_app}-${version.number}/AdHoc" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/somesource/**\ /tmp/build/trunk/Libraries/somemoresource/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        

        为您的临时版本创建配置,并确保它使用临时准备好的配置文件。或者,您可以创建一个使用您的开发人员配置文件的普通、非临时配置。如果您使用前者,您可以将产品连同您的配置文件一起通过电子邮件发送给测试人员。如果您执行后者,您可以使用 iPhone 配置实用程序在配置文件中的任何设备上进行安装。

        此外,我们的 ANT 目标设置依赖于从源代码管理进行新的检查并从那里进行构建。最后,我们使用真正的 App Store 就绪配置进行构建,这样我们就可以测试第一个构建并将第二个构建交付给 Apple,并在一定程度上确定代码行为将是相同的。

        以下是按处理顺序对我们的 ANT 目标进行的摘要:

        1. 设置构建所需的环境变量
        2. 清除结帐和构建目录
        3. 从源代码管理中签出 HEAD
        4. 修改 plist 以删除调试和元素仅供内部使用(使用 PLISTBUDDY)
        5. 增量构建版本(使用 agvtool)
        6. 运行单元测试(这需要将 sdk 设置设置为 iphonesimulator4.x 和一个特殊目标 - 请参阅 iPhone 开发人员指南了解单元测试)
        7. 进行内部构建(使用开发配置文件或临时配置文件)
        8. 进行分发构建(使用 App Store 分发证书)
        9. 签入具有新构建版本的 plist 文件
        10. 在源代码管理中添加一个标记来指示构建
        11. 报告构建统计信息(构建版本、位置等)

        注意:确保您在 xcodebuild 命令语法中设置了 SYMROOT 环境变量,以便您的构建最终位于正确的目录中。事后我们在复制 App Store 版本时遇到了问题。

        这是用于创建多个构建的完整 ANT 脚本,一个用于测试,一个用于分发。例如:“ant distribution”将使用 dev 配置文件创建一个构建,并使用 App Store 分发配置文件创建一个。

        这个脚本是“清理过的”,所以它只是作为一个开始的模型:

        <?xml version="1.0" ?>
        
        <project basedir="." default="xcode-build" name="Temp">
            <property file="build.properties" />
            <property name = "CONFIGURATION_INTERNAL" value = "InternalRelease" />
            <property name = "CONFIGURATION_DISTRIBUTION" value = "Distribution" />
            <property name = "CONFIGURATION_ADHOC" value = "InternalAdHoc" />
            <property name="cvsroot" value=":pserver:${username}:${password}@${cvsurl}"/>
            <tstamp>
              <format property="TODAY"
                      pattern="MM-dd-yyyy"
                      locale="en,US"/>
            </tstamp>
        
        
            <target name="init">
                <echo message="deleting old directories" />
                <delete dir="${check_out_location}"/>
                <mkdir dir="${check_out_location}"/>
            </target>
        
        
            <target name="set-source-trees" depends="init">
            <echo message="exporting source tree variables" />
                <echo message="${somesourcedir}" />
                <exec executable="/bin/bash" os=" Mac OS X">
                    <arg value="-c" />
                    <arg value="${export_src_trees}"/>
                    <arg value="${anothersourcedir}"/>
                </exec>
                <exec executable="/bin/bash" os=" Mac OS X">
                    <arg value="-c" />
                    <arg value="${export_src_trees}"/>
                    <arg value="${yetanothersourcedir}"/>
                </exec>
            </target>
        
        
            <target name="cvs-login" depends="init" description="CVS Login">
                <echo>Login CVS</echo>
                <cvs cvsroot=":pserver:${username}:${password}@${cvsurl}" command="login" />
            </target>
        
            <target name="checkout" depends="cvs-login" description="Check out source from CVS">
                <echo message="check out from CVS ...." />
                <echo message="${check_out_location}" />
                <cvs cvsroot="${cvsroot}"  command=" -Q checkout -P -d${project_trunk} ${project_repository_root}/${project_trunk} " dest="${check_out_location}" compression="true" />
                <echo message="...check out from CVS done" />
            </target>
        
        
             <target name="strip-settings" depends="checkout" description="Remove elements from the Settings.bundle that we don't want in the distribution">
                <echo message="Removing Settings not valid for distribution"/>
        
                <exec executable="/usr/libexec/PlistBuddy" failonerror="TRUE" dir="${app_src}/Resources">
                    <arg value="-c"/>
                    <arg value="Delete :PreferenceSpecifiers:3"/>
                    <arg value="Settings.bundle/Root.plist"/>
                </exec>
        
                <exec executable="/usr/libexec/PlistBuddy" failonerror="TRUE" dir="${app_src}/Resources">
                    <arg value="-c"/>
                    <arg value="Delete :PreferenceSpecifiers:3"/>
                    <arg value="Settings.bundle/Root.plist"/>
                </exec>
            </target>
        
        
            <target name="build-version" depends="checkout">
        
                <property name = "LOGLEVEL" value = "DEBUG" />
        
               <!-- GET THE NEXT VERSION NUMBER (major and minor) -->
                <exec executable="/tmp/build/trunk/Build/version.sh" failonerror="TRUE" outputproperty="version.number" dir="${app_src}"></exec>
        
                <echo message="Increment Build Number"/>
        
                <exec executable="agvtool" failonerror="TRUE" dir="${app_src}">
                    <arg value="new-version"/>
                    <arg value="-all"/>
                    <arg value="${version.number}"/>
                </exec>
        
                <!-- GET THE MINOR portion of the version number for later use -->
                <exec executable="/tmp/build/trunk/Build/minor.sh" failonerror="TRUE" outputproperty="version.minor" dir="${app_src}"></exec>
        
                <!-- SET the version number as reference in the Settings.bundle -->
                <exec executable="/usr/libexec/PlistBuddy" failonerror="TRUE" dir="${app_src}">
                    <arg value="-c"/>
                    <arg value="Set :PreferenceSpecifiers:1:DefaultValue ${version.number}"/>
                    <arg value="./Resources/Settings.bundle/Root.plist"/>
                </exec>
        
                <echo message="New build number=${version.number}"/>
        
                <!-- SET the log level - NOTE, ANT vars are immutable, if LOGLEVEL was previously set, it cannot be overridden -->
                <exec executable="/usr/libexec/PlistBuddy" failonerror="TRUE" dir="${app_src}">
                    <arg value="-c"/>
                    <arg value="Set LogLevel.Default ${LOGLEVEL}"/>
                    <arg value="./Resources/SharedConfig.plist"/>
                </exec>
                <echo message="Log level set to ${LOGLEVEL}"/>
        
            </target>
        
        
             <target name="encrypt" depends="build-version">
                <!-- SOME ENCRYPTION OF SENSITIVE DATA -->
            </target>
        
        
            <target name="build-internal" depends="test-lib1, test-lib2, test-app, encrypt">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${app_src}">
                    <arg value="clean"/>
                    <arg value="install"/>    
                    <arg value="-target" />
                    <arg value="MyApp" />
                    <arg value="-configuration"/>
                    <arg value="${CONFIGURATION_INTERNAL}"/>
                    <arg value="SYMROOT=${build_release}" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/somesource/**\ /tmp/build/trunk/Libraries/someothersource/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
             <target name="test-lib1" depends="checkout">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${somelib_dir}">
                    <arg value="clean"/>
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="Lib1UnitTests"/>
                    <arg value="-sdk"/>
                    <arg value="iphonesimulator4.1"/>
                    <arg value="SYMROOT=${build_release}" />
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
             <target name="test-lib2" depends="checkout">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${somelib2_src_dir}">
                    <arg value="clean"/>
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="Lib2UnitTests"/>
                    <arg value="-sdk"/>
                    <arg value="iphonesimulator4.1"/>
                    <arg value="SYMROOT=${build_release}" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/Lib1source/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
              <target name="test-app" depends="checkout">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${app_src}">
                    <arg value="clean"/>
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="AppUnitTests"/>
                    <arg value="-sdk"/>
                    <arg value="iphonesimulator4.1"/>
                    <arg value="SYMROOT=${build_release}" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/Lib1/**\ /tmp/build/trunk/Libraries/Lib2/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
             <target name="build-distribution" depends="internal-release, test-lib1, test-lib2, test-app">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${app_src}">
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="MyApp" />
                    <arg value="-configuration"/>
                    <arg value="${CONFIGURATION_DISTRIBUTION}"/>
                    <arg value="SYMROOT=${export_app}-${version.number}/Distribution" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/Lib1/**\ /tmp/build/trunk/Libraries/Lib2/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
            <target name="build-adhoc" depends="internal-release, test-lib1, test-lib2, test-app">
                <echo>Running XCODE compiler</echo>
                <exec executable="${xcode_builder}" failonerror="true" vmlauncher="false" dir="${app_src}">
                    <arg value="build"/>
                    <arg value="-target" />
                    <arg value="MyApp" />
                    <arg value="-configuration"/>
                    <arg value="${CONFIGURATION_ADHOC}"/>
                    <arg value="SYMROOT=${export_app}-${version.number}/AdHoc" />
                    <env key="USER_HEADER_SEARCH_PATHS" value="/tmp/build/trunk/Libraries/Lib1/**\ /tmp/build/trunk/Libraries/Lib2/**"/>
                </exec>
                <echo>xcode build complete</echo>
            </target>
        
        
            <target name="checkin" depends="build-internal" description="Commit source to CVS" >
                <echo message="Committing to CVS ...." />
                <echo message="${check_out_location}" />
        
                 <cvs cvsroot="${cvsroot}"  command="commit -m 'Commit of internal release build ${version.number}' MyApp-Info.plist" dest="${check_out_location}/trunk/Applications/MyApp" />
                <echo message="...commit done" />
            </target>
        
        
             <target name="tag-release" depends="checkin" description="Tag source in CVS" >
                <echo message="Tagging source ... Release-${version.minor}" />
                <echo message="${check_out_location}" />
                <cvs cvsroot="${cvsroot}"  command="tag Release-${version.minor}" dest="${check_out_location}"/>
                <echo message="...tag done" />
            </target>
        
        
             <target name="internal-release" depends="tag-release" description="Tag source in CVS" >
                <echo message="Creating Internal release ..." />
                <echo message="Deploying files to . . .${export_app}" />
                <copy todir="${export_app}-${version.number}">
                    <fileset dir="${prod_dir_internal}"/>
                </copy>
        
                <echo message="Internal release ${version.number} complete." />
            </target>
        
        
             <target name="override-default-env"  description="Setup Env for Distribution" >
                        <property name = "LOGLEVEL" value = "WARN" />
             </target>
        
        
             <target name="distribution" depends="override-default-env, strip-settings, build-distribution" description="Create Distribution" >
        
                <echo message="Creating Distribution ..." />
                <echo message="Deploying files to . . .${export_app}-${version.number}/Distribution" />
                <echo message="Distribution ${version.number} complete." />
        
            </target>
        
             <target name="adhoc" depends="override-default-env, strip-settings, build-adhoc" description="Create Ad Hoc Distribution" >
        
                <echo message="Creating ad hoc distribution ..." />
                <echo message="Deploying files to . . .${export_app}-${version.number}/AdHoc" />
                <echo message="Ad hoc distribution ${version.number} complete." />
        
            </target>
        
        
        </project>
        
        Hope this helps.
        

        【讨论】:

        • 感谢您的回答,但我不想改变当前的构建过程 - 我不是在谈论单元测试。
        • 对不起丹尼尔。我给出的答案应该可以帮助您验证要发送到 App Store 的代码库,尽管它不会帮助您验证实际的可执行文件。另一种方法是重新签署产品,以便您可以使用 codesign util 将其安装在许多 ad hoc 机器上进行认证。
        猜你喜欢
        • 1970-01-01
        • 2012-09-09
        • 1970-01-01
        • 1970-01-01
        • 2012-04-21
        • 1970-01-01
        • 2015-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多