线上第七期_iOS 测试技术_20181110

iOS基础

开发者中心

证书申请

  • 创建证书
  • 使用keychain的证书助手创建CSR文件

XCode

  • 项目
  • Git
  • Symbol
  • Find
  • Issue
  • 调试
  • 测试
  • 报告

关键概念

Certificates:苹果签发
开发证书:开发者使用
发布证书:对外分化到app store或者使用ad-hoc模式分发
Provisioning Profiles:
App ID:bundleID相关设置
Devices List:可内测的真机列表
分为开发和发布两种大类型
发布又分为ad-hoc、app store、enterprise级别
.app文件:编译后生成的项目打包代码
.ipa文件:经过签名后的打包文件,本质是zip文件

编译

模拟器

CodeSign /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Products/Debug-iphonesimulator/iOSDemo.app (in target: iOSDemo)
    cd /Volumes/ram/xcode/iOSDemo
    export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
    
Signing Identity:     "-"

    /usr/bin/codesign --force --sign - --entitlements /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Intermediates.noindex/iOSDemo.build/Debug-iphonesimulator/iOSDemo.build/iOSDemo.app.xcent --timestamp=none /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Products/Debug-iphonesimulator/iOSDemo.app

真机构建

CodeSign /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Products/Debug-iphoneos/iOSDemo.app (in target: iOSDemo)
    cd /Volumes/ram/xcode/iOSDemo
    export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
    
Signing Identity:     "iPhone Developer: yansheng huang (LJGDR784H2)"
Provisioning Profile: "iOS Team Provisioning Profile: *"
                      (0c3891ec-b6a3-4bd8-bb3c-1774087952ff)

    /usr/bin/codesign --force --sign A747E05F425FF31AA6180C146F9BE554AA1983B6 --entitlements /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Intermediates.noindex/iOSDemo.build/Debug-iphoneos/iOSDemo.build/iOSDemo.app.xcent --timestamp=none /Users/seveniruby/Library/Developer/Xcode/DerivedData/iOSDemo-elmdjvdeutixwufmutvahqycagvt/Build/Products/Debug-iphoneos/iOSDemo.app

常见命令

ls ~/Library/MobileDevice/Provisioning\\ Profiles
security find-identity -p codesigning


#安装appium的前提
#http://appium.io/docs/en/drivers/ios-xcuitest-real-devices/
brew install libimobiledevice
brew install ios-deploy

依赖工具包安装:
brew install --HEAD ideviceinstaller
brew install --HEAD libimobiledevice
brew install ios-deploy
查看模拟器列表:instruments -s devices
查看真机列表:idevice_id -l
安装app: ideviceinstaller -i demo.app
命令行编译:
xcodebuild -scheme UICatalog -target iOS clean build
xcodebuild -scheme UICatalog -target iOS archive

WebDriverAgent

git clone https://github.com/facebook/WebDriverAgent.git
cd WebDriverAgent/
bash -x  ./Scripts/bootstrap.sh

start
https://github.com/facebook/WebDriverAgent/wiki/Using-the-Inspector

Inspector
http://localhost:8100/inspector

Appium iOS测试

appium desktop error

[XCUITest] WDA is not listening at 'http://localhost:8100/'
[XCUITest] WDA is currently not running. There is nothing to cache
[XCUITest] Trying to start WebDriverAgent 2 times with 10000ms interval
[BaseDriver] Event 'wdaStartAttempted' logged at 1541831315367 (14:28:35 GMT+0800 (CST))
[XCUITest] Launching WebDriverAgent on the device
[XCUITest] Carthage found: '/usr/local/bin/carthage'
[XCUITest] Killing running processes 'xcodebuild.*BB022D2E-9903-4A11-9D18-926B7F0F2447, iproxy 8100, BB022D2E-9903-4A11-9D18-926B7F0F2447.*XCTRunner' for the device BB022D2E-9903-4A11-9D18-926B7F0F2447...
[XCUITest] 'pgrep -nif xcodebuild.*BB022D2E-9903-4A11-9D18-926B7F0F2447' didn't detect any matching processes. Return code: 1
[XCUITest] 'pgrep -nif iproxy 8100' didn't detect any matching processes. Return code: 1
[XCUITest] 'pgrep -nif BB022D2E-9903-4A11-9D18-926B7F0F2447.*XCTRunner' didn't detect any matching processes. Return code: 1
[XCUITest] Beginning test with command 'xcodebuild build-for-testing test-without-building -project /Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination id=BB022D2E-9903-4A11-9D18-926B7F0F2447 IPHONEOS_DEPLOYMENT_TARGET=11.0' in directory '/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent'
[XCUITest] Output from xcodebuild will not be logged. To change this, use 'showXcodeLog' desired capability
[XCUITest] Waiting up to 60000ms for WebDriverAgent to start

xcodebuild error

2018-11-10 14:49:39:565 - info: [Xcode] Details:  stringRep should be a non-empty string, but it's an empty string
2018-11-10 14:49:39:566 - info: [Xcode] Object:   <DVTMacroDefinitionConditionSet>
2018-11-10 14:49:39:566 - info: [Xcode] Method:   +conditionSetFromStringRepresentation:getBaseMacroName:error:
2018-11-10 14:49:39:566 - info: [Xcode] Thread:   <NSThread: 0x7fd84f502350>{number = 1, name = main}
2018-11-10 14:49:39:566 - info: [Xcode] Hints:
2018-11-10 14:49:39:567 - info: [Xcode]
2018-11-10 14:49:39:567 - info: [Xcode] Backtrace:
2018-11-10 14:49:39:574 - info: [Xcode]   0   -[DVTAssertionHandler handleFailureInMethod:object:fileName:lineNumber:assertionSignature:messageFormat:arguments:] (in DVTFoundation)
2018-11-10 14:49:39:575 - info: [Xcode]   1   _DVTAssertionHandler (in DVTFoundation)
2018-11-10 14:49:39:575 - info: [Xcode]   2   _DVTAssertionFailureHandler (in DVTFoundation)
2018-11-10 14:49:39:576 - info: [Xcode]   3   +[DVTMacroDefinitionConditionSet conditionSetFromStringRepresentation:getBaseMacroName:error:] (in DVTFoundation)
2018-11-10 14:49:39:576 - info: [Xcode]   4   -[DVTMacroDefinitionTable(XCMacroExpansionExtensions) _xc_setValue:forMacroName:errorHandler:] (in DevToolsCore)
2018-11-10 14:49:39:577 - info: [Xcode]   5   __108-[DVTMacroDefinitionTable(XCMacroExpansionExtensions) xc_setMacroNamesAndValuesFromDictionary:errorHandler:]_block_invoke (in DevToolsCore)
2018-11-10 14:49:39:580 - info: [Xcode]   6   -[__NSFrozenDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] (in CoreFoundation)
2018-11-10 14:49:39:582 - info: [Xcode]   7   -[DVTMacroDefinitionTable(XCMacroExpansionExtensions) xc_setMacroNamesAndValuesFromDictionary:errorHandler:] (in DevToolsCore)
2018-11-10 14:49:39:583 - info: [Xcode]   8   -[NSProcessInfo(XCMacroExpansionExtensions) xc_cachedEnvironmentAsMacroDefinitionTable] (in DevToolsCore)
2018-11-10 14:49:39:583 - info: [Xcode]   9   -[PBXTarget createMacroExpansionScopeWithBuildParameters:] (in DevToolsCore)
2018-11-10 14:49:39:583 - info: [Xcode]  10   -[PBXTarget cachedMacroExpansionScopeForBuildParameters:] (in DevToolsCore)
2018-11-10 14:49:39:583 - info: [Xcode]  11   -[PBXTarget expandedValueForString:forBuildParameters:] (in DevToolsCore)
2018-11-10 14:49:39:584 - info: [Xcode]  12   -[PBXNativeTarget fullProductNameForBuildParameters:] (in DevToolsCore)
2018-11-10 14:49:39:584 - info: [Xcode]  13   -[PBXNativeTarget fullProductNameForConfigurationNamed:] (in DevToolsCore)
2018-11-10 14:49:39:585 - info: [Xcode]  14   -[PBXTarget fullProductName] (in DevToolsCore)
2018-11-10 14:49:39:586 - info: [Xcode]  15   -[PBXReference setProducingTarget:] (in DevToolsCore)
2018-11-10 14:49:39:586 - info: [Xcode]  16   -[PBXTarget awakeFromPListUnarchiver:] (in DevToolsCore)
2018-11-10 14:49:39:587 - info: [Xcode]  17   -[PBXNativeTarget awakeFromPListUnarchiver:] (in DevToolsCore)
2018-11-10 14:49:39:587 - info: [Xcode]  18   -[PBXPListUnarchiver decodeRootObject] (in DevToolsCore)
2018-11-10 14:49:39:587 - info: [Xcode]  19   +[PBXProject projectWithFile:errorHandler:readOnly:] (in DevToolsCore)
2018-11-10 14:49:39:588 - info: [Xcode]  20   -[Xcode3Project initWithFilePath:extension:workspace:options:error:] (in DevToolsCore)
2018-11-10 14:49:39:588 - info: [Xcode]  21   __82+[IDEContainer _retainedContainerAtFilePath:fileDataType:workspace:options:error:]_block_invoke_2 (in IDEFoundation)
2018-11-10 14:49:39:589 - info: [Xcode]  22   _dispatch_client_callout (in libdispatch.dylib)
2018-11-10 14:49:39:589 - info: [Xcode]  23   _dispatch_lane_barrier_sync_invoke_and_complete (in libdispatch.dylib)
2018-11-10 14:49:39:590 - info: [Xcode]  24   DVTDispatchBarrierSync (in DVTFoundation)
2018-11-10 14:49:39:590 - info: [Xcode]  25   -[DVTDispatchLock performLockedBlock:] (in DVTFoundation)
2018-11-10 14:49:39:591 - info: [Xcode]  26   __82+[IDEContainer _retainedContainerAtFilePath:fileDataType:workspace:options:error:]_block_invoke (in IDEFoundation)
2018-11-10 14:49:39:592 - info: [Xcode]  27   __58-[DVTModelObjectGraph performBlockCoalescingModelChanges:]_block_invoke (in DVTFoundation)
2018-11-10 14:49:39:593 - info: [Xcode]  28   -[DVTModelGraphTransactionScope performTransaction:] (in DVTFoundation)
2018-11-10 14:49:39:593 - info: [Xcode]  29   -[DVTModelObjectGraph performBlockCoalescingModelChanges:] (in DVTFoundation)
2018-11-10 14:49:39:594 - info: [Xcode]  30   +[IDEContainer _retainedContainerAtFilePath:fileDataType:workspace:options:error:] (in IDEFoundation)
2018-11-10 14:49:39:594 - info: [Xcode]  31   +[IDEContainer retainedContainerAtFilePath:fileDataType:workspace:error:] (in IDEFoundation)
2018-11-10 14:49:39:595 - info: [Xcode]  32   -[IDEWorkspace _configureWrappedWorkspaceWithError:] (in IDEFoundation)
2018-11-10 14:49:39:595 - info: [Xcode]  33   __82+[IDEContainer _retainedContainerAtFilePath:fileDataType:workspace:options:error:]_block_invoke (in IDEFoundation)
2018-11-10 14:49:39:595 - info: [Xcode]  34   +[IDEContainer _retainedContainerAtFilePath:fileDataType:workspace:options:error:] (in IDEFoundation)
2018-11-10 14:49:39:595 - info: [Xcode]  35   +[IDEContainer retainedWrappedWorkspaceForContainerAtFilePath:fileDataType:error:] (in IDEFoundation)
2018-11-10 14:49:39:596 - info: [Xcode]  36   -[Xcode3CommandLineBuildTool _resolveInputOptionsWithTimingSection:] (in Xcode3Core)
2018-11-10 14:49:39:596 - info: [Xcode]  37   -[Xcode3CommandLineBuildTool run] (in Xcode3Core)
2018-11-10 14:49:39:596 - info: [Xcode]  38   main (in xcodebuild)
2018-11-10 14:49:39:596 - info: [Xcode]  39   start (in libdyld.dylib)
2018-11-10 14:49:39:597 - info: [Xcode]
2018-11-10 14:49:39:602 - info: [XCUITest] xcodebuild exited with code 'null' and signal 'SIGABRT'

核心编译命令

Beginning test with command 'xcodebuild build-for-testing test-without-building -project /Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination id=BB022D2E-9903-4A11-9D18-926B7F0F2447 IPHONEOS_DEPLOYMENT_TARGET=11.0' in directory '/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-xcuitest-driver/WebDriverAgent'
2018-11-10 14:48:53:338 - info: [debug] [XCUITest] Output from xcodebuild will be logged. To change this, use 'showXcodeLog' desired capability
``

## SImulator控制
https://github.com/facebook/FBSimulatorControl/blob/master/fbsimctl/README.md


## 模拟器示例

```java
package ios7;

import io.appium.java_client.MobileElement;
import io.appium.java_client.ios.IOSDriver;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities;

public class DemoTest {

    private IOSDriver driver;

    @Before
    public void setUp() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        desiredCapabilities.setCapability("platformName", "ios");
        desiredCapabilities.setCapability("deviceName", "iPhone X");
        desiredCapabilities.setCapability("platformVersion", "11.0");
        desiredCapabilities.setCapability("automationName", "xcuitest");
        desiredCapabilities.setCapability("app", "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-ftyzdbgapjmxxobezrnrxsshpdqh/Build/Products/Debug-iphonesimulator/UICatalog.app");
        //desiredCapabilities.setCapability("showXcodeLog", "true");

        URL remoteUrl = new URL("http://127.0.0.1:4723/wd/hub");

        driver = new IOSDriver(remoteUrl, desiredCapabilities);
    }

    @Test
    public void sampleTest() {
        driver.findElementByAccessibilityId("Buttons").click();
        System.out.println(driver.getPageSource());
        driver.findElementByXPath("//*[@label='Button']").click();
        driver.findElementByAccessibilityId("UICatalog").click();
    }

    @After
    public void tearDown() {
        //driver.quit();
    }
}

真机测试

error

[ 52%] CreatingStagingDirectory
[ 57%] ExtractingPackage
[ 60%] InspectingPackage
[ 60%] TakingInstallLock
[ 65%] PreflightingApplication
[ 70%] VerifyingApplication
2018-11-10 16:07:23.798 ios-deploy[54447:2782396] [ !! ] Error 0xe8000067: There was an internal API error. AMDeviceSecureInstallApplication(0, device, url, options, install_callback, 0)

真机需要的capability

  • udid: auto
  • xcodeOrgId
  • xcodeSigningId
{
  "platformName": "ios",
  "deviceName": "iPhone X",
  "platformVersion": "11.0",
  "automationName": "xcuitest",
  "showXcodeLog": "true",
  "udid": "auto",
  "xcodeOrgId": "96NJEQL7Y2",
  "xcodeSigningId": "iPhone Developer"
}

Browser

brew install --HEAD libimobiledevice
brew install ios-webkit-debug-proxy
settings > safari > advanced > web inspector → on

package ios7;

import io.appium.java_client.MobileElement;
import io.appium.java_client.ios.IOSDriver;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.remote.DesiredCapabilities;

public class WebTest {

    private IOSDriver driver;

    @Before
    public void setUp() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        desiredCapabilities.setCapability("platformName", "ios");
        desiredCapabilities.setCapability("automationName", "xcuitest");
        desiredCapabilities.setCapability("udid", "auto");
        desiredCapabilities.setCapability("startIWDP", "true");
        desiredCapabilities.setCapability("browserName", "Safari");
        desiredCapabilities.setCapability("deviceName", "auto");

        URL remoteUrl = new URL("http://127.0.0.1:4723/wd/hub");

        driver = new IOSDriver(remoteUrl, desiredCapabilities);
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
    }

    @Test
    public void sampleTest() {
        driver.get("https://testerhome.com");
        driver.findElementByXPath("//*[contains(@title, '广州沙龙')]").click();
    }

    @After
    public void tearDown() {
        //driver.quit();
    }
}

WebView

package ios7;

import io.appium.java_client.MobileElement;
import io.appium.java_client.ios.IOSDriver;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities;

public class WebViewTest {

    private IOSDriver driver;

    @Before
    public void setUp() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        desiredCapabilities.setCapability("platformName", "ios");
        desiredCapabilities.setCapability("deviceName", "iPhone X");
        desiredCapabilities.setCapability("platformVersion", "11.0");
        desiredCapabilities.setCapability("automationName", "xcuitest");
        desiredCapabilities.setCapability("showXcodeLog", "true");
        desiredCapabilities.setCapability("udid", "auto");
        desiredCapabilities.setCapability("xcodeOrgId", "96NJEQL7Y2");
        desiredCapabilities.setCapability("xcodeSigningId", "iPhone Developer");
        desiredCapabilities.setCapability("app", "/Users/seveniruby/Library/Developer/Xcode/DerivedData/UICatalog-ftyzdbgapjmxxobezrnrxsshpdqh/Build/Products/Debug-iphoneos/UICatalog.app");
        desiredCapabilities.setCapability("startIWDP", "true");

        URL remoteUrl = new URL("http://127.0.0.1:4723/wd/hub");

        driver = new IOSDriver(remoteUrl, desiredCapabilities);
    }

    @Test
    public void sampleTest() throws InterruptedException {
        driver.findElementByXPath("//XCUIElementTypeButton[@name=\\"UICatalog\\"]").click();
        driver.findElementByAccessibilityId("Web View").click();
        Thread.sleep(6000);
        System.out.println(driver.getContextHandles());
        System.out.println(driver.getPageSource());
        driver.context("WEBVIEW_1");
        System.out.println(driver.getPageSource());
    }

    @After
    public void tearDown() {
        driver.quit();
    }
}