Skip to content

Commit fd36189

Browse files
authored
chore(ci/cd):Generate build reports from DF data (#1136)
* chore(ci/cd):Generate build reports from DF data
1 parent c0dcc7a commit fd36189

File tree

5 files changed

+113
-5
lines changed

5 files changed

+113
-5
lines changed

configuration/instrumentation-tests.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Need to create backends for s3, pinpoint, predictions, core
44
*/
55
def module_backends = [
6-
'aws-datastore':'DataStoreInstrumentedTests',
6+
'aws-datastore':'DataStoreIntegTests',
77
'aws-api': 'ApiInstrumentedTests',
88
'aws-storage-s3': 'NONE',
99
'aws-analytics-pinpoint': 'NONE',
@@ -34,7 +34,7 @@ task pullBackendConfigFromAmplify(description: "Pulls backend configurations fro
3434
def amplifyBackendProjectName = entry.value
3535

3636
println("Getting config files for $amplifyBackendProjectName")
37-
def amplifyPullCommand = "$rootDir.path/scripts/pull_backend_config_from_amplify.sh"
37+
def amplifyPullCommand = "$rootDir.path/scripts/pull_backend_config_from_amplify"
3838
exec {
3939
workingDir(rootDir.path)
4040
executable(amplifyPullCommand)

scripts/devicefarm-test-runner-buildspec.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ phases:
1818
runtime-versions:
1919
android: 29
2020
nodejs: 12
21+
python: 3.8
2122
commands:
2223
- echo 'Install phase starting'
24+
- npm install -g xunit-viewer
25+
- pip3 install junit-xml
2326
finally:
2427
- echo 'Install phase completed.'
2528
pre_build:
@@ -45,10 +48,26 @@ phases:
4548
post_build:
4649
commands:
4750
- echo 'Post-build phase starting'
51+
- mkdir -p build/reports/instrumented
52+
- xunit-viewer -r build/allTests -o build/reports/instrumented/${CODEBUILD_RESOLVED_SOURCE_VERSION}.html
4853
finally:
4954
- echo 'Post-build phase completed.'
55+
reports:
56+
amplify-android-devicefarm-tests:
57+
files:
58+
- '**/*'
59+
base-directory: 'build/allTests'
60+
discard-paths: no
61+
file-format: JUNITXML
5062
artifacts:
5163
files:
5264
- '**/*.apk'
5365
name: AmplifyAndroidCatApks
54-
discard-paths: yes
66+
discard-paths: yes
67+
secondary-artifacts:
68+
reports:
69+
files:
70+
- '**/*'
71+
name: DevicefarmTestRunReport
72+
base-directory: 'build/reports/instrumented'
73+
discard-paths: no

scripts/generate_df_testrun_report

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
"""Python script that generates a user-readable report for a given DeviceFarm test run.
3+
"""
4+
5+
import os
6+
import sys
7+
import subprocess
8+
import argparse
9+
import logging
10+
import boto3
11+
from botocore.config import Config
12+
from junit_xml import TestSuite, TestCase
13+
14+
LOG_FORMATTER = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
15+
CONSOLE_HANDLER = logging.StreamHandler()
16+
CONSOLE_HANDLER.setFormatter(LOG_FORMATTER)
17+
LOGGER = logging.getLogger("DeviceFarmTestRunReportGenerator")
18+
LOGGER.setLevel(os.getenv("LOG_LEVEL") if os.getenv("LOG_LEVEL") is not None else "INFO")
19+
LOGGER.addHandler(CONSOLE_HANDLER)
20+
21+
client = boto3.client('devicefarm', config=Config(region_name='us-west-2'))
22+
23+
def parse_arguments():
24+
parser = argparse.ArgumentParser(description="Utility that generates a report for a DeviceFarm test run.")
25+
parser.add_argument("--run_arn", help="The ARN of the DeviceFarm test run.", required=True)
26+
parser.add_argument("--module_name", help="The module name for the test suite.", required=True)
27+
parser.add_argument("--output_path", help="Destination path for the build reports.", required=True)
28+
parser.add_argument("--pr", help="The github PR number.")
29+
return parser.parse_args()
30+
31+
def generate_junit_report(run_arn, output_path):
32+
LOGGER.debug(f"Retrieving test jobs for run {run_arn}")
33+
jobs = get_test_jobs(run_arn)
34+
for job in jobs:
35+
LOGGER.debug(f"Retrieving test suites for job {job['arn']}")
36+
suites = get_test_suites(job['arn'])
37+
for suite in suites:
38+
LOGGER.debug(f"Retrieving tests for suite {suite['arn']}")
39+
tests = get_tests(suite['arn'])
40+
test_cases = []
41+
for test in tests:
42+
tc = TestCase(test['name'],
43+
classname=suite['name'],
44+
elapsed_sec=test['deviceMinutes']['total']*60,
45+
stdout=test['message'],
46+
status=test['result'] )
47+
if test['result'] == 'FAILED':
48+
tc.add_failure_info(message=test['message'])
49+
if test['result'] == 'ERROR':
50+
tc.add_error_info(message=test['message'])
51+
test_cases.append(tc)
52+
ts = TestSuite(suite['name'],test_cases=test_cases)
53+
ts_output = TestSuite.to_xml_string([ts])
54+
LOGGER.info(f"Saving test suite {suite['name']} report.")
55+
if not os.path.exists(output_path):
56+
os.makedirs(output_path)
57+
f = open(output_path + suite['name'] + ".xml", "w")
58+
f.write(ts_output)
59+
f.close()
60+
61+
def get_test_jobs(run_arn):
62+
result = client.list_jobs(arn=run_arn)
63+
return result['jobs'] if result is not None else []
64+
65+
def get_test_suites(job_arn):
66+
result = client.list_suites(arn=job_arn)
67+
return result['suites'] if result is not None else []
68+
69+
def get_tests(suite_arn):
70+
result = client.list_tests(arn=suite_arn)
71+
return result['tests'] if result is not None else []
72+
73+
def get_problems(run_arn):
74+
return client.list_unique_problems(
75+
arn=run_arn
76+
)
77+
78+
def main(arguments):
79+
args = parse_arguments()
80+
build_id = os.getenv("CODEBUILD_BUILD_ID")
81+
source_version = os.getenv("CODEBUILD_SOURCE_VERSION")
82+
arn_suffix = args.run_arn.split(':')[-1]
83+
LOGGER.info(f"devicefarm_run: {arn_suffix} build_id: {build_id} source_version: {source_version}")
84+
generate_junit_report(run_arn=args.run_arn,
85+
output_path=args.output_path)
86+
87+
if __name__ == '__main__':
88+
sys.exit(main(sys.argv[1:]))

scripts/pull_backend_config_from_amplify

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ amplify pull \
2424
--yes
2525
echo "Current dir is $(pwd)"
2626
mkdir -p $res_dir
27-
cp -R ./config_files/* $res_dir
27+
cp -R ./config_files/raw/* $res_dir
2828
ls -al $res_dir
2929
cd $base_dir
3030
echo "Completed project $project_name"

scripts/run_test_in_devicefarm.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,15 @@ while true; do
6767
read -a result_arr <<< $run_status_response
6868
status=${result_arr[0]}
6969
result=${result_arr[1]}
70-
echo "Status = $status Result = $result"
7170
if [ "$status" = "COMPLETED" ]
7271
then
7372
break
7473
fi
7574
sleep 5
7675
done
76+
echo "Status = $status Result = $result"
7777

78+
./scripts/generate_df_testrun_report --run_arn="$run_arn" --module_name="$module_name" --pr="$CODEBUILD_SOURCE_VERSION" --output_path="build/allTests/$module_name/"
7879
# If the result is PASSED, then exit with a return code 0
7980
if [ "$result" = "PASSED" ]
8081
then

0 commit comments

Comments
 (0)