运行 在 Browserstack 上自动测试时 apk 和 espresso apk 之间的签名不匹配
Signature mismatch between apk & espresso apk when running tests on Browserstack automate
我在 Azure 上编写了一个管道来构建我们的 apk,构建 espresso 测试 apk,使用位于安全存储中的 Keystore 对它们进行签名,然后将它们上传到 BrowserStack 自动化并执行测试。该问题出现在 Browserstack 上的 Builds 仪表板上,其中显示:
There is signature mismatch between application APK and test-suite APK. Package com.example.appName.test does not have a signature matching the target package com.example.appName. Please fix this, upload your app & test-suite APK and execute the test again.
这是 my.yml 文件:
pool:
vmImage: ubuntu-latest
steps:
# download .jks file from secure files for signing
- task: DownloadSecureFile@1
name: keystore
displayName: 'Download keystore file'
inputs:
secureFile: 'appName.jks'
- script: |
echo Installing $(keystore.secureFilePath) to the trusted keystore directory...
sudo chown root:root $(keystore.secureFilePath)
sudo chmod a+r $(keystore.secureFilePath)
sudo ln -s -t /etc/ssl/certs/ $(keystore.secureFilePath)
displayName: "Installing keystore file"
# build apk
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleGoogleDebug'
displayName: "Building default APK"
# Build test apk
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleGoogleDebugAndroidTest'
displayName: "Building test APK"
# sign the apks with the same signature
- task: AndroidSigning@3
inputs:
apkFiles: '**/*.apk'
apksignerKeystoreFile: 'appName.jks'
apksignerKeystorePassword: '***'
apksignerKeystoreAlias: 'appName'
apksignerKeyPassword: '***'
zipalign: false
displayName: "Signing APKs"
- task: BrowserStackConfig@0
inputs:
BrowserStackServiceEndPoint: 'BrowserStack connection'
displayName: "Establishing BrowserStack connection..."
# Upload apk to BrowserStack
- task: BrowserStackAppUploader@0
inputs:
appPath: '/home/vsts/work/1/s/presentation/build/outputs/apk/google/debug/presentation-google-debug.apk'
appCustomId: 'sport24'
displayName: 'Uploading default APK to BrowserStack'
- script: |
curl -u "name:key" \
-X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite" \
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk"
-F "custom_id=appNameTest"
echo "triggering test"
curl -u "name:key" \
-X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" \
-d '{"app": "url", "testSuite": "bs://url", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
-H "Content-Type: application/json"
displayName: 'uploading test suite and triggering test'
# post test results
- task: BrowserStackResults@0
我正在使用相同的密钥库对两个 APK 进行签名,并且测试 class 位于 com.example.appName/androidTest/
下,所以我无法弄清楚是什么导致了不匹配。有什么想法吗?
当我从 Jenkins 将我的 apk 上传到 BrowserStack 时,我遇到了完全相同的问题。我的管道有单独的步骤来构建 debug.apk 和 androidTest.apk。然而,我只签署了我的 release.apk,这是一个单独的步骤。
我通过一步构建 debug.apk 和 androidTest.apk 成功解决了这个问题。
所以在我的 Jenkinsfile
中,我结合了这两个步骤
stage("Build Debug APK") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew assembleDebug'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
}
}
stage("UI Tests") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew :app:assembleAndroidTest'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
// Upload apks to BrowserStack
}
进入以下:
stage("UI Tests") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew assembleDebug :app:assembleAndroidTest'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
// Upload apks to BrowserStack
}
因此,要解决您的问题,您还可以尝试将 assembleGoogleDebug
和 assembleGoogleDebugAndroidTest
合并为一个步骤。
这个错误的发生似乎有多种原因。
查看您的 .yml
文件,我可以提出以下 2 项更正建议:
- 您在指定测试套件的自定义 ID 的
-F
参数之前缺少反斜杠 \
,这是必需的,否则将不会设置测试套件的自定义 ID , 所以替换这一行:
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk"
这一行(只需在末尾添加 \
):
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk" \
- 在触发测试执行的最终 curl 命令中,您应该将 URL 替换为您为应用程序和测试套件设置的自定义 ID。
所以编辑这一行:
-d '{"app": "url", "testSuite": "bs://url", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
为此:
-d '{"app": "INSERT_CUSTOM_APP_ID_HERE", "testSuite": "INSERT_CUSTOM_TEST_ID_HERE", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
以上更改基本上是您现在使用您之前设置的 ID 指定用于测试执行的应用程序和测试套件,这与使用 URL 不同,每次执行可能会导致首先是错误。
我在 Azure 上编写了一个管道来构建我们的 apk,构建 espresso 测试 apk,使用位于安全存储中的 Keystore 对它们进行签名,然后将它们上传到 BrowserStack 自动化并执行测试。该问题出现在 Browserstack 上的 Builds 仪表板上,其中显示:
There is signature mismatch between application APK and test-suite APK. Package com.example.appName.test does not have a signature matching the target package com.example.appName. Please fix this, upload your app & test-suite APK and execute the test again.
这是 my.yml 文件:
pool:
vmImage: ubuntu-latest
steps:
# download .jks file from secure files for signing
- task: DownloadSecureFile@1
name: keystore
displayName: 'Download keystore file'
inputs:
secureFile: 'appName.jks'
- script: |
echo Installing $(keystore.secureFilePath) to the trusted keystore directory...
sudo chown root:root $(keystore.secureFilePath)
sudo chmod a+r $(keystore.secureFilePath)
sudo ln -s -t /etc/ssl/certs/ $(keystore.secureFilePath)
displayName: "Installing keystore file"
# build apk
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleGoogleDebug'
displayName: "Building default APK"
# Build test apk
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleGoogleDebugAndroidTest'
displayName: "Building test APK"
# sign the apks with the same signature
- task: AndroidSigning@3
inputs:
apkFiles: '**/*.apk'
apksignerKeystoreFile: 'appName.jks'
apksignerKeystorePassword: '***'
apksignerKeystoreAlias: 'appName'
apksignerKeyPassword: '***'
zipalign: false
displayName: "Signing APKs"
- task: BrowserStackConfig@0
inputs:
BrowserStackServiceEndPoint: 'BrowserStack connection'
displayName: "Establishing BrowserStack connection..."
# Upload apk to BrowserStack
- task: BrowserStackAppUploader@0
inputs:
appPath: '/home/vsts/work/1/s/presentation/build/outputs/apk/google/debug/presentation-google-debug.apk'
appCustomId: 'sport24'
displayName: 'Uploading default APK to BrowserStack'
- script: |
curl -u "name:key" \
-X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite" \
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk"
-F "custom_id=appNameTest"
echo "triggering test"
curl -u "name:key" \
-X POST "https://api-cloud.browserstack.com/app-automate/espresso/v2/build" \
-d '{"app": "url", "testSuite": "bs://url", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
-H "Content-Type: application/json"
displayName: 'uploading test suite and triggering test'
# post test results
- task: BrowserStackResults@0
我正在使用相同的密钥库对两个 APK 进行签名,并且测试 class 位于 com.example.appName/androidTest/
下,所以我无法弄清楚是什么导致了不匹配。有什么想法吗?
当我从 Jenkins 将我的 apk 上传到 BrowserStack 时,我遇到了完全相同的问题。我的管道有单独的步骤来构建 debug.apk 和 androidTest.apk。然而,我只签署了我的 release.apk,这是一个单独的步骤。
我通过一步构建 debug.apk 和 androidTest.apk 成功解决了这个问题。
所以在我的 Jenkinsfile
中,我结合了这两个步骤
stage("Build Debug APK") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew assembleDebug'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
}
}
stage("UI Tests") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew :app:assembleAndroidTest'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
// Upload apks to BrowserStack
}
进入以下:
stage("UI Tests") {
withDockerContainer (image: image) {
sh script: 'bash ./gradlew assembleDebug :app:assembleAndroidTest'
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.apk', onlyIfSuccessful: false
// Upload apks to BrowserStack
}
因此,要解决您的问题,您还可以尝试将 assembleGoogleDebug
和 assembleGoogleDebugAndroidTest
合并为一个步骤。
这个错误的发生似乎有多种原因。
查看您的 .yml
文件,我可以提出以下 2 项更正建议:
- 您在指定测试套件的自定义 ID 的
-F
参数之前缺少反斜杠\
,这是必需的,否则将不会设置测试套件的自定义 ID , 所以替换这一行:
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk"
这一行(只需在末尾添加 \
):
-F "file=@ /home/vsts/work/1/s/presentation/build/outputs/apk/androidTest/google/debug/presentation-google-debug-androidTest.apk" \
- 在触发测试执行的最终 curl 命令中,您应该将 URL 替换为您为应用程序和测试套件设置的自定义 ID。
所以编辑这一行:
-d '{"app": "url", "testSuite": "bs://url", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
为此:
-d '{"app": "INSERT_CUSTOM_APP_ID_HERE", "testSuite": "INSERT_CUSTOM_TEST_ID_HERE", "devices": ["Samsung Galaxy S9 Plus-9.0"]}' \
以上更改基本上是您现在使用您之前设置的 ID 指定用于测试执行的应用程序和测试套件,这与使用 URL 不同,每次执行可能会导致首先是错误。