Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MTE-3753 Fetch multiple test suites and upload to Google Cloud bucket #46

Merged
merged 22 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions .github/workflows/testrail-backup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:

jobs:
test:
name: Run unit tests
runs-on: macos-14
name: Backup test suites
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backup-tools
Expand All @@ -28,13 +28,25 @@ jobs:

- name: Install dependencies
run: |
python install -r requirements.txt
pip install -r requirements.txt

- name: Establish Google Cloud connection
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCLOUD_AUTH }}

- name: Fetch test cases
run: |
python backup_testrail.py

- name: Upload to GCP bucket (todo)
run: |
echo "TODO"
head *.csv
today=`date "+%Y-%m-%d"`
mkdir $today
cp *.csv $today
pwd
ls $today
echo "today=$today" >> $GITHUB_ENV

- name: Upload CSV to GCP bucket
uses: google-github-actions/upload-cloud-storage@v2
with:
path: backup-tools/${{ env.today }}
destination: backups-testrail-test-suites
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ android-performance/node_modules
actions-runner
backup-tools/*.csv
backup-tools/*.json
backup-tools/__pychache__/
backup-tools/__pychache__/
*.pyc
28 changes: 28 additions & 0 deletions backup-tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# TestRail Backup Tool

This directory holds the source code for backing up selected test suites to the designated
Google Cloud bucket on a regular basis.

## Recover from backup

1. Download the CSV file from the Google Cloud bucket.
1. Download the .cfg file from this directory.
1. Navigate to TestRail project's *TestSuites & Cases* tab and open to an empty test suite.
1. Select *Import Cases* icon ➡️ *Import From CSV*.
1. From the *Import from CSV* modal:
* Select the CSV file from step 1.
* Select *Load mapping from configuration file* and select the .cfg file from step 1.
* Select *UTF-8* as *File Encoding*.
* Select *Test Case (Steps)* as the *Template*
* Click *Next*
1. From the 2nd *Import from CSV* modal:
* Select *Test cases use multiple rows*
* Select *Title* as the *Column to detect new test cases*
* Click *Next* until the *Preview Import* screen
* (Configure the mapping for custom fields)
1. Click *Import* and then *Close*.

## Todo and Limitations

* No custom fields in .cfg file.
* [Administrator instructions](https://support.testrail.com/hc/en-us/articles/7373850291220-Configuring-custom-fields) for setting custom fields
100 changes: 45 additions & 55 deletions backup-tools/backup_testrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,34 @@
import csv
from datetime import datetime
from testrail import TestRail
from pathvalidate import sanitize_filename

PROJECT = {
'Fenix Browser': {
'id': 59,
'suite': {
'Full Functional Tests Suite': 3192
}
},
'Firefox for iOS': {
'id': 14,
'suite': {
'Full Functional Tests Suite': 45443,
'iOS Performance Test Suite': 1298
}
},
'Focus for iOS': {
'id': 27,
'suite': {
'Full Functional Test Suite': 5291
}
},
'Firefox for Android': {
'id': 13,
'suite': {
'Smoke Tests': 142,
'L10N Test suite': 186
}
},
'Focus for Android': {
'id': 49,
'suite': {
'Full Functional Tests Suite': 1028
}
}
}

if __name__ == "__main__":
def create_csv(project_id, project_name, suite_id, suite_name):
print("Fetching {project}: {suite}".format(project=project_name, suite=suite_name))

testrail = TestRail()
now = datetime.now()
testrail = TestRail()
response = testrail.test_cases(project_id, suite_id)

project = 'Firefox for iOS'
suite = 'Full Functional Tests Suite'
PROJECT_ID = PROJECT.get(project).get('id')
SUITE_ID = PROJECT.get(project).get('suite').get(suite)

response = testrail.test_cases(PROJECT_ID, SUITE_ID)
# Get only the cases only
test_case = response['cases']
cases = response['cases']

# Do not create backup for empty suites
if len(cases) == 0:
return

output_json_file = "data-{project}-{suite}-{year}-{month}-{day}.json".format(
project=project,
suite=suite,
project=project_name,
suite=suite_name,
year=now.year,
month=now.month,
day=now.day
)
output_json_file = sanitize_filename(output_json_file)

# write test cases to json file
# Write test cases to json file (For debugging)
with open(output_json_file, 'w') as output:
json.dump(test_case, output, indent=2)
json.dump(cases, output, indent=2)

# write test cases to CSV file
output_csv_file = output_json_file.replace(".json", ".csv")
Expand All @@ -72,20 +39,43 @@

# Print header
# Rearrange the multi-line steps and expected result to be at the rightmost
backup_fields = [*test_case[0].keys()]
backup_fields = [*cases[0].keys()]
backup_fields.remove('custom_steps_separated')
backup_fields.append('Steps')
backup_fields.append('Expected Result')
csv_writer.writerow(backup_fields)

# Print rows (including unravel the Steps and Expected Results)
for test in test_case[1:-1]:
first_row = [test[field] for field in backup_fields[:-2]] # need treatment for steps
first_row.append(test['custom_steps_separated'][0]['content'])
first_row.append(test['custom_steps_separated'][0]['expected'])
for case in cases[1:-1]:
first_row = [case.get(field, '') for field in backup_fields[:-2]] # need treatment for steps
steps = case['custom_steps_separated']
if steps:
first_row.append(steps[0].get('content', ''))
first_row.append(steps[0].get('expected', ''))
else:
first_row.append('')
first_row.append('')
steps = []
csv_writer.writerow(first_row)
for step in test['custom_steps_separated'][1:-1]:

for step in steps[1:-1]:
row = ["" for field in backup_fields[:-2]]
row.append(step['content'])
row.append(step['expected'])
csv_writer.writerow(row)
csv_writer.writerow(row)

if __name__ == "__main__":
testrail = TestRail()

# Fenix Browser, Firefox for iOS, Focus for iOS, Firefox for Android, Focus for Android
# for project_id in [59, 14, 27, 13, 48]:

for project_id in [59, 14, 27, 13, 48]:
project = testrail.project(project_id)
project_name = project.get('name')
suites = testrail.test_suites(project_id)

for suite in suites:
suite_id = suite.get('id')
suite_name = suite.get('name')
create_csv(project_id, project_name, suite_id, suite_name)
2 changes: 2 additions & 0 deletions backup-tools/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests==2.32.3
pathvalidate==3.2.1
1 change: 1 addition & 0 deletions backup-tools/testrail-import.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"import":{"format":"csv","version":1},"file":{"encoding":"UTF-8","delimiter":",","start_row":1,"has_header":true,"skip_empty":true},"layout":{"format":"multi","break":1,"template":2},"columns":["","cases:title","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","cases:custom_steps_separated.content","cases:custom_steps_separated.expected"],"values":{"1":{"remove_html":false},"34":{"remove_html":false},"35":{"remove_html":false}}}
Loading