I currently have an Azure DevOps YAML pipeline that I use to run my WebdriverIO test suites in CI. If an Azure user selects 'all-suites', the pipeline should create an individual pipeline task for every suite. Currently, I have an individual pipeline script for every single suite I'm running, but I'm trying to figure out a way to use YAML syntax to iterate over a list of test suite names instead. This way, I don't have to manually add repetitive blocks of code every time I add a suite to my app. You can see my current pipeline file pattern here-
parameters:
- name: testSuite
type: string
default: 'all-suites'
values:
- 'all-suites'
- 'suite1'
- 'suite2'
- 'suite3'
trigger: none
jobs:
- job: run_pipeline
timeoutInMinutes: 120
displayName: 'Run'
pool:
vmImage: 'ubuntu-latest'
steps:
# if the user doesn't select 'all-suites', it runs the specific suite selected as a single task
- ${{ if ne(parameters.testSuite, 'all-suites') }}:
- script: |
npm run example-command -- --suite ${{ parameters.testSuite }}
displayName: 'Run test suite: ${{ parameters.testSuite }}'
continueOnError: true
# if the user does select 'all-suites', it runs specific tasks for each suite
- ${{ if eq(parameters.testSuite, 'all-suites') }}:
- script: |
npm run example-command -- --suite suite1
displayName: 'suite1'
continueOnError: true
- script: |
npm run example-command -- --suite suite2
displayName: 'suite2'
continueOnError: true
- script: |
npm run example-command -- --suite suite3
displayName: 'suite3'
continueOnError: true
Rather than having to manually add a new block every time I add a new suite, I was hoping I could iterate over something like this -
steps:
- ${{ if ne(parameters.testSuite, 'all-suites') }}:
- script: |
npm run example-command -- --suite ${{ parameters.testSuite }}
displayName: 'Run test suite: ${{ parameters.testSuite }}'
continueOnError: true
- ${{ if eq(parameters.testSuite, 'all-suites') }}:
- ${{ each suite in <SUITE LIST HERE> }}:
# skip 'all-suites' because it's not a real suite
- ${{ if ne(suite, 'all-suites') }}:
- script: |
npm run example-command -- --suite ${{ suite }}
displayName: '${{ suite }}'
continueOnError: true
From what I've read, I can't access any sort of list in this way if it isn't available during compile, so I was wondering if anyone knew of any creative ways to create a list that is in fact available during compile.
This would be a workaround but it will work
parameters:
- name: testSuite
type: string
default: 'all-suites'
values:
- 'all-suites'
- 'suite1'
- 'suite2'
- 'suite3'
- name: suiteList
type: object
default:
- 'suite1'
- 'suite2'
- 'suite3'
steps:
- ${{ if ne(parameters.testSuite, 'all-suites') }}:
- script: |
npm run example-command -- --suite ${{ parameters.testSuite }}
displayName: 'Run test suite: ${{ parameters.testSuite }}'
continueOnError: true
- ${{ if eq(parameters.testSuite, 'all-suites') }}:
- ${{ each suite in parameters.suiteList }}:
- script: |
npm run example-command -- --suite ${{ suite }}
displayName: '${{ suite }}'
continueOnError: true
The disadvantage of this that you have duplication of suite names in parameters.
You could also try use if else
here
parameters:
- name: testSuite
type: string
default: 'all-suites'
values:
- 'all-suites'
- 'suite1'
- 'suite2'
- 'suite3'
- name: suiteList
type: object
default:
- 'suite1'
- 'suite2'
- 'suite3'
steps:
- ${{ if ne(parameters.testSuite, 'all-suites') }}:
- script: |
npm run example-command -- --suite ${{ parameters.testSuite }}
displayName: 'Run test suite: ${{ parameters.testSuite }}'
continueOnError: true
- ${{ else }}:
- ${{ each suite in parameters.suiteList }}:
- script: |
npm run example-command -- --suite ${{ suite }}
displayName: '${{ suite }}'
continueOnError: true