mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
batsExecuteTests - add step for executing bats-core (#254)
details are available in the documentation contained in this PR
This commit is contained in:
parent
e49633a7d2
commit
17ee927807
77
documentation/docs/steps/batsExecuteTests.md
Normal file
77
documentation/docs/steps/batsExecuteTests.md
Normal file
@ -0,0 +1,77 @@
|
||||
# batsExecuteTests
|
||||
|
||||
## Description
|
||||
|
||||
This step executes tests using the [Bash Automated Testing System - bats-core](https://github.com/bats-core/bats-core)
|
||||
|
||||
## Prerequsites
|
||||
|
||||
You need to have a Bats test file. By default you would put this into directory `src/test` within your source code repository.
|
||||
|
||||
## Parameters
|
||||
|
||||
| parameter | mandatory | default | possible values |
|
||||
|-----------|-----------|---------|-----------------|
|
||||
| script | no | empty `globalPipelineEnvironment` | |
|
||||
| dockerImage | no | `node:8-stretch` | |
|
||||
| dockerWorkspace | no |`/home/node`| |
|
||||
| envVars | no | `[:]` | |
|
||||
| failOnError | no | `false` | |
|
||||
| gitBranch | no | | |
|
||||
| gitSshKeyCredentialsId | no | | |
|
||||
| outputFormat | no | `junit` | `tap` |
|
||||
| repository | no | `https://github.com/bats-core/bats-core.git` | |
|
||||
| stashContent | no | `['tests']` | |
|
||||
| testPackage | no | `piper-bats` | |
|
||||
| testPath | no | `src/test`| |
|
||||
| testRepository | no | | |
|
||||
|
||||
|
||||
Details:
|
||||
|
||||
* `outputFormat` defines the format of the test result output. `junit` would be the standard for automated build environments but you could use also the option `tap`.
|
||||
* For the transformation of the test result to xUnit format the node module **tap-xunit** is used. `dockerImage` and `dockerWorkspace` define the Docker image used for the transformation and `testPackage` defines the name of the test package used in the xUnit result file.
|
||||
* `testPath` defines either the directory which contains the test files (`*.bats`) or a single file. You can find further details in the [Bats-core documentation](https://github.com/bats-core/bats-core#usage)
|
||||
* With `failOnError` you can define the behavior, in case tests fail. For example, in case of `outputFormat: 'junit'` you should set it to `false`. Otherwise test results cannot be recorded using the `testsPublishhResults` step afterwards.
|
||||
* You can pass environment variables to the test execution by defining parameter `envVars`.
|
||||
|
||||
With `envVars` it is possible to pass either fixed values but also templates using [`commonPipelineEnvironment`](commonPipelineEnvironment.md).
|
||||
|
||||
Example:
|
||||
```
|
||||
batsExecuteTests script: this, envVars = [
|
||||
FIX_VALUE: 'my fixed value',
|
||||
CONTAINER_NAME: '${commonPipelineEnvironment.configuration.steps.executeBatsTests.dockerContainerName}',
|
||||
IMAGE_NAME: '${return commonPipelineEnvironment.getDockerImageNameAndTag()}'
|
||||
]
|
||||
```
|
||||
|
||||
This means within the test one could refer to environment variables by calling e.g.
|
||||
`run docker run --rm -i --name $CONTAINER_NAME --entrypoint /bin/bash $IMAGE_NAME echo "Test"`
|
||||
|
||||
* Using parameters `testRepository` the tests can be loaded from another reposirory. In case the tests are not located in the master branch the branch can be specified with `gitBranch`. For protected repositories you can also define the access credentials via `gitSshKeyCredentialsId`. **Note: In case of using a protected repository, `testRepository` should include the ssh link to the repository.**
|
||||
* The parameter `repository` defines the version of **bats-core** to be used. By default we use the version from the master branch.
|
||||
|
||||
## Step configuration
|
||||
The following parameters can also be specified as step/stage/general parameters using the [global configuration](../configuration.md):
|
||||
|
||||
* dockerImage
|
||||
* dockerWorkspace
|
||||
* envVars
|
||||
* failOnError
|
||||
* gitBranch
|
||||
* gitSshKeyCredentialsId
|
||||
* outputFormat
|
||||
* repository
|
||||
* stashContent
|
||||
* testPackage
|
||||
* testPath
|
||||
* testRepository
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```groovy
|
||||
batsExecuteTests script:this
|
||||
testsPublishResults junit: [pattern: '**/Test-*.xml', archive: true]
|
||||
```
|
@ -4,6 +4,7 @@ pages:
|
||||
- Configuration: configuration.md
|
||||
- 'Library steps':
|
||||
- artifactSetVersion: steps/artifactSetVersion.md
|
||||
- batsExecuteTests: steps/batsExecuteTests.md
|
||||
- checkChangeInDevelopment: steps/checkChangeInDevelopment.md
|
||||
- cloudFoundryDeploy: steps/cloudFoundryDeploy.md
|
||||
- commonPipelineEnvironment: steps/commonPipelineEnvironment.md
|
||||
|
@ -42,6 +42,17 @@ steps:
|
||||
sbt:
|
||||
filePath: 'sbtDescriptor.json'
|
||||
versioningTemplate: '${version}-${timestamp}${commitId?"+"+commitId:""}'
|
||||
batsExecuteTests:
|
||||
dockerImage: 'node:8-stretch'
|
||||
dockerWorkspace: '/home/node'
|
||||
envVars: {}
|
||||
outputFormat: 'junit' # tap, junit
|
||||
testPath: 'src/test'
|
||||
failOnError: false
|
||||
repository: 'https://github.com/bats-core/bats-core.git'
|
||||
stashContent:
|
||||
- 'tests'
|
||||
testPackage: 'piper-bats'
|
||||
checksPublishResults:
|
||||
aggregation:
|
||||
active: true
|
||||
|
143
test/groovy/BatsExecuteTestsTest.groovy
Normal file
143
test/groovy/BatsExecuteTestsTest.groovy
Normal file
@ -0,0 +1,143 @@
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.*
|
||||
|
||||
import static org.hamcrest.Matchers.hasItem
|
||||
import static org.hamcrest.Matchers.is
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class BatsExecuteTestsTest extends BasePiperTest {
|
||||
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
private JenkinsStepRule jsr = new JenkinsStepRule(this)
|
||||
private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
|
||||
private JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
|
||||
private JenkinsDockerExecuteRule jder = new JenkinsDockerExecuteRule(this)
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(thrown)
|
||||
.around(jder)
|
||||
.around(jscr)
|
||||
.around(jlr)
|
||||
.around(jsr)
|
||||
|
||||
List withEnvArgs = []
|
||||
|
||||
@Before
|
||||
void init() throws Exception {
|
||||
helper.registerAllowedMethod("withEnv", [List.class, Closure.class], {arguments, closure ->
|
||||
arguments.each {arg ->
|
||||
withEnvArgs.add(arg.toString())
|
||||
}
|
||||
return closure()
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefault() {
|
||||
nullScript.commonPipelineEnvironment.configuration = [general: [container: 'test-container']]
|
||||
jsr.step.batsExecuteTests(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
dockerContainerName: 'test-container',
|
||||
dockerImageNameAndTag: 'test/image',
|
||||
envVars: [
|
||||
IMAGE_NAME: 'test/image',
|
||||
CONTAINER_NAME: '${commonPipelineEnvironment.configuration.general.container}'
|
||||
],
|
||||
testPackage: 'testPackage'
|
||||
)
|
||||
// asserts
|
||||
assertThat(withEnvArgs, hasItem('IMAGE_NAME=test/image'))
|
||||
assertThat(withEnvArgs, hasItem('CONTAINER_NAME=test-container'))
|
||||
assertThat(jscr.shell, hasItem('git clone https://github.com/bats-core/bats-core.git'))
|
||||
assertThat(jscr.shell, hasItem('bats-core/bin/bats --recursive --tap src/test > \'TEST-testPackage.tap\''))
|
||||
assertThat(jscr.shell, hasItem('cat \'TEST-testPackage.tap\''))
|
||||
|
||||
assertThat(jder.dockerParams.dockerImage, is('node:8-stretch'))
|
||||
assertThat(jder.dockerParams.dockerWorkspace, is('/home/node'))
|
||||
|
||||
assertThat(jscr.shell, hasItem('npm install tap-xunit -g'))
|
||||
assertThat(jscr.shell, hasItem('cat \'TEST-testPackage.tap\' | tap-xunit --package=\'testPackage\' > TEST-testPackage.xml'))
|
||||
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTap() {
|
||||
jsr.step.batsExecuteTests(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
outputFormat: 'tap'
|
||||
)
|
||||
assertThat(jder.dockerParams.size(), is(0))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailOnError() {
|
||||
helper.registerAllowedMethod('sh', [String.class], {s ->
|
||||
if (s.startsWith('bats-core/bin/bats')) {
|
||||
throw new Exception('Shell call failed')
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
})
|
||||
thrown.expectMessage('Shell call failed')
|
||||
jsr.step.batsExecuteTests(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
failOnError: true,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGit() {
|
||||
def gitRepository
|
||||
helper.registerAllowedMethod('git', [Map.class], {m ->
|
||||
gitRepository = m
|
||||
})
|
||||
helper.registerAllowedMethod('stash', [String.class], {s ->
|
||||
assertThat(s, is('batsTests'))
|
||||
})
|
||||
|
||||
jsr.step.batsExecuteTests(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
testRepository: 'testRepo',
|
||||
)
|
||||
|
||||
assertThat(gitRepository.size(), is(1))
|
||||
assertThat(gitRepository.url, is('testRepo'))
|
||||
assertThat(jder.dockerParams.stashContent, hasItem('batsTests'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGitBranchAndCredentials() {
|
||||
def gitRepository
|
||||
helper.registerAllowedMethod('git', [Map.class], {m ->
|
||||
gitRepository = m
|
||||
})
|
||||
helper.registerAllowedMethod('stash', [String.class], {s ->
|
||||
assertThat(s, is('batsTests'))
|
||||
})
|
||||
|
||||
jsr.step.batsExecuteTests(
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
gitBranch: 'test',
|
||||
gitSshKeyCredentialsId: 'testCredentials',
|
||||
testRepository: 'testRepo',
|
||||
)
|
||||
assertThat(gitRepository.size(), is(3))
|
||||
assertThat(gitRepository.credentialsId, is('testCredentials'))
|
||||
assertThat(gitRepository.branch, is('test'))
|
||||
}
|
||||
|
||||
|
||||
}
|
80
vars/batsExecuteTests.groovy
Normal file
80
vars/batsExecuteTests.groovy
Normal file
@ -0,0 +1,80 @@
|
||||
import com.sap.piper.Utils
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import groovy.text.SimpleTemplateEngine
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field String STEP_NAME = 'batsExecuteTests'
|
||||
@Field Set STEP_CONFIG_KEYS = [
|
||||
'dockerImage', //
|
||||
'dockerWorkspace',
|
||||
'envVars',
|
||||
'failOnError',
|
||||
'gitBranch',
|
||||
'gitSshKeyCredentialsId',
|
||||
'outputFormat',
|
||||
'repository',
|
||||
'stashContent',
|
||||
'testPackage',
|
||||
'testPath',
|
||||
'testRepository'
|
||||
]
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
def call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
|
||||
|
||||
def utils = parameters.juStabUtils ?: new Utils()
|
||||
def script = parameters.script ?: [commonPipelineEnvironment: commonPipelineEnvironment]
|
||||
|
||||
Map config = ConfigurationHelper
|
||||
.loadStepDefaults(this)
|
||||
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
|
||||
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
|
||||
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
|
||||
.mixin(parameters, PARAMETER_KEYS)
|
||||
.use()
|
||||
|
||||
// report to SWA
|
||||
utils.pushToSWA([step: STEP_NAME], config)
|
||||
|
||||
script.commonPipelineEnvironment.setInfluxStepData('bats', false)
|
||||
|
||||
|
||||
if (config.testRepository) {
|
||||
def gitParameters = [url: config.testRepository]
|
||||
if (config.gitSshKeyCredentialsId?.length()>0) gitParameters.credentialsId = config.gitSshKeyCredentialsId
|
||||
if (config.gitBranch?.length()>0) gitParameters.branch = config.gitBranch
|
||||
git gitParameters
|
||||
stash 'batsTests'
|
||||
config.stashContent = ['batsTests']
|
||||
} else {
|
||||
config.stashContent = utils.unstashAll(config.stashContent)
|
||||
}
|
||||
|
||||
//resolve commonPipelineEnvironment references in envVars
|
||||
config.envVarList = []
|
||||
config.envVars.each {e ->
|
||||
def envValue = SimpleTemplateEngine.newInstance().createTemplate(e.getValue()).make(commonPipelineEnvironment: script.commonPipelineEnvironment).toString()
|
||||
config.envVarList.add("${e.getKey()}=${envValue}")
|
||||
}
|
||||
|
||||
withEnv(config.envVarList) {
|
||||
sh "git clone ${config.repository}"
|
||||
try {
|
||||
sh "bats-core/bin/bats --recursive --tap ${config.testPath} > 'TEST-${config.testPackage}.tap'"
|
||||
script.commonPipelineEnvironment.setInfluxStepData('bats', true)
|
||||
} catch (err) {
|
||||
echo "[${STEP_NAME}] One or more tests failed"
|
||||
if (config.failOnError) throw err
|
||||
} finally {
|
||||
sh "cat 'TEST-${config.testPackage}.tap'"
|
||||
if (config.outputFormat == 'junit') {
|
||||
dockerExecute(dockerImage: config.dockerImage, dockerWorkspace: config.dockerWorkspace, stashContent: config.stashContent) {
|
||||
sh "npm install tap-xunit -g"
|
||||
sh "cat 'TEST-${config.testPackage}.tap' | tap-xunit --package='${config.testPackage}' > TEST-${config.testPackage}.xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -96,6 +96,14 @@ class commonPipelineEnvironment implements Serializable {
|
||||
return influxCustomDataMap
|
||||
}
|
||||
|
||||
def setInfluxStepData (dataKey, value) {
|
||||
influxCustomDataMap.step_data[dataKey] = value
|
||||
}
|
||||
def getInfluxStepData (dataKey) {
|
||||
return influxCustomDataMap.step_data[dataKey]
|
||||
}
|
||||
|
||||
|
||||
def getMtarFilePath() {
|
||||
return mtarFilePath
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user