0

I'll try being as detailed as I possibly can. Please excuse any formatting or language issues.

What I'm trying to do?

I'm trying to make an app to upload APKs to Appcenter to execute UI test cases on whatever devices a user provided. When finished, my app will show the results of the UI tests executed.

How am I doing it?

App center has provided a lot of APIs which may be viewed here. Executing a UI test is a 4 step process.

  1. Create a new test run. This is working
  2. Create hashses of files to be uploaded. This is working
  3. Upload the actual files. I keep getting a 400 bad request OR "payload is too big" error. My APK file is only 1 MB & the upload works through Appcenter CLI.
  4. Execute the test run created. This API is not working. Probably due to failure of 3rd step.

What do I need help with?

Step 3. above is not working for me. I keep getting the following error when I try to upload the APK file through curl/postman.

Curl command :

curl -i -F "data=@app-debug-androidTest.apk" -H "X-API-Token:API_TOKEN_HERE" -H "Content-Type:application/json" -X POST https://api.appcenter.ms/v0.1/apps/{ORG_NAME}/{APP_NAME}/test_runs/{TEST_RUN_ID_CREATED_IN_STEP_1}/files

Error received :

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>Payload Too Large</pre>
    </body>
</html>

The irony is, when the exact same API is executed by the Appcenter CLI, it works. If UI tests are executed as part of the build step, App center uses the exact same procedure & set of APIs to upload the APK. Please view the complete log here. For formatting purposes, I did not add in inline.

What am I doing wrong?

Clinkz
  • 716
  • 5
  • 18

2 Answers2

1

Your curl command in step 3 is trying to upload the binary file as multipart form data (in a param data that doesn't exist in the API spec). The /files endpoint expects no file upload, but is preparing the upload internally and then returns the upload URL to you. See here in the App Center CLI's code:

const directUrl = await this.getDirectUploadUrl(this._client, testRunId, file);
await this.makeDirectUpload(directUrl, file);

Remove -F "data=@app-debug-androidTest.apk" from your curl command, then check the response for the upload URL for this test run.

ashtom
  • 804
  • 1
  • 8
  • 13
  • The API spec is incomplete for a lot of APIs. It turns out `/file` need not be called at all even though its part of CLI tool. Posting what worked for me as a separate answer. Thanks for taking the time to investigate. – Clinkz Jun 08 '18 at 14:36
1

After a day and half, possibly two I was able to resolve this issue. I've posted an elaborate document here & below is the shorter version.

Once you've created a new test run, you need to upload your file hashes for the APKs generated from the gradle command $ ./gradlew clean assembleDebug assembleAndroidTest. The URL is mentioned in the location key in the response of /hashes/batch API. The body of the API will be similar to :

[{
        "file_type":"app-file",
        "checksum":"df798b4d07597db804546b8ca723780992811111", //Calculate your file's SHA-1 by using shasum util
        "relative_path":"app-debug.apk"
}]

Now we upload the file on the URL received in response to the /hashes/batch API with the following body params in form-data format.

  • relative_path //The name of the file is adequate
  • file //The actual file
  • file_type //app-file for build APK and test-file for APK containing espresso tests

If the files upload properly, you may execute the test run by /start API end point.

Clinkz
  • 716
  • 5
  • 18