1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-12 10:55:20 +02:00

feat(karma): migrate karmaExecuteTests to go implementation (#2695)

* convert karmaExecuteTests to go implementation

* removed KarmaExecuteTestsTest.groovy

* added KarmaExecuteTests to fieldRelatedWhiteList

* Update vars/karmaExecuteTests.groovy

Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>

* Update resources/metadata/karmaExecuteTests.yaml

Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>

* Update resources/metadata/karmaExecuteTests.yaml

Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>

* added reference seleniumHubCredentialsId to yaml file, fixed modules code

* karmaExecuteTests.yaml renamed to karma.yaml

Co-authored-by: lndrschlz <leander.schulz01@sap.com>
Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>
This commit is contained in:
Mikalai Dzemidzenka 2021-04-15 14:58:23 +03:00 committed by GitHub
parent d04a7c2eb3
commit 61f4c5245a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 250 deletions

View File

@ -19,23 +19,27 @@ func karmaExecuteTests(config karmaExecuteTestsOptions, telemetryData *telemetry
func runKarma(config karmaExecuteTestsOptions, command command.ExecRunner) {
installCommandTokens := tokenize(config.InstallCommand)
command.SetDir(config.ModulePath)
err := command.RunExecutable(installCommandTokens[0], installCommandTokens[1:]...)
if err != nil {
log.Entry().
WithError(err).
WithField("command", config.InstallCommand).
Fatal("failed to execute install command")
}
runCommandTokens := tokenize(config.RunCommand)
command.SetDir(config.ModulePath)
err = command.RunExecutable(runCommandTokens[0], runCommandTokens[1:]...)
if err != nil {
log.Entry().
WithError(err).
WithField("command", config.RunCommand).
Fatal("failed to execute run command")
modulePaths := config.Modules
for _, module := range modulePaths {
command.SetDir(module)
err := command.RunExecutable(installCommandTokens[0], installCommandTokens[1:]...)
if err != nil {
log.Entry().
WithError(err).
WithField("command", config.InstallCommand).
Fatal("failed to execute install command")
}
command.SetDir(module)
err = command.RunExecutable(runCommandTokens[0], runCommandTokens[1:]...)
if err != nil {
log.Entry().
WithError(err).
WithField("command", config.RunCommand).
Fatal("failed to execute run command")
}
}
}

View File

@ -14,9 +14,9 @@ import (
)
type karmaExecuteTestsOptions struct {
InstallCommand string `json:"installCommand,omitempty"`
ModulePath string `json:"modulePath,omitempty"`
RunCommand string `json:"runCommand,omitempty"`
InstallCommand string `json:"installCommand,omitempty"`
Modules []string `json:"modules,omitempty"`
RunCommand string `json:"runCommand,omitempty"`
}
// KarmaExecuteTestsCommand Executes the Karma test runner
@ -87,11 +87,11 @@ In the Docker network, the containers can be referenced by the values provided i
func addKarmaExecuteTestsFlags(cmd *cobra.Command, stepConfig *karmaExecuteTestsOptions) {
cmd.Flags().StringVar(&stepConfig.InstallCommand, "installCommand", `npm install --quiet`, "The command that is executed to install the test tool.")
cmd.Flags().StringVar(&stepConfig.ModulePath, "modulePath", `.`, "Define the path of the module to execute tests on.")
cmd.Flags().StringSliceVar(&stepConfig.Modules, "modules", []string{`.`}, "Define the paths of the modules to execute tests on.")
cmd.Flags().StringVar(&stepConfig.RunCommand, "runCommand", `npm run karma`, "The command that is executed to start the tests.")
cmd.MarkFlagRequired("installCommand")
cmd.MarkFlagRequired("modulePath")
cmd.MarkFlagRequired("modules")
cmd.MarkFlagRequired("runCommand")
}
@ -119,10 +119,10 @@ func karmaExecuteTestsMetadata() config.StepData {
Aliases: []config.Alias{},
},
{
Name: "modulePath",
Name: "modules",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Type: "[]string",
Mandatory: true,
Aliases: []config.Alias{},
},

View File

@ -2,16 +2,17 @@ package cmd
import (
"errors"
"github.com/SAP/jenkins-library/pkg/mock"
"testing"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/stretchr/testify/assert"
)
func TestRunKarma(t *testing.T) {
t.Run("success case", func(t *testing.T) {
opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "npm install test", RunCommand: "npm run test"}
opts := karmaExecuteTestsOptions{Modules: []string{"./test"}, InstallCommand: "npm install test", RunCommand: "npm run test"}
e := mock.ExecMockRunner{}
runKarma(opts, &e)
@ -28,7 +29,7 @@ func TestRunKarma(t *testing.T) {
var hasFailed bool
log.Entry().Logger.ExitFunc = func(int) { hasFailed = true }
opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "fail install test", RunCommand: "npm run test"}
opts := karmaExecuteTestsOptions{Modules: []string{"./test"}, InstallCommand: "fail install test", RunCommand: "npm run test"}
e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"fail install test": errors.New("error case")}}
runKarma(opts, &e)
@ -39,7 +40,7 @@ func TestRunKarma(t *testing.T) {
var hasFailed bool
log.Entry().Logger.ExitFunc = func(int) { hasFailed = true }
opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "npm install test", RunCommand: "npm run test"}
opts := karmaExecuteTestsOptions{Modules: []string{"./test"}, InstallCommand: "npm install test", RunCommand: "npm run test"}
e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"npm install test": errors.New("error case")}}
runKarma(opts, &e)

View File

@ -15,6 +15,10 @@ metadata:
In a Kubernetes environment, the containers both need to be referenced with `localhost`.
spec:
inputs:
secrets:
- name: seleniumHubCredentialsId
type: jenkins
description: "Defines the id of the user/password credentials to be used to connect to a Selenium Hub. The credentials are provided in the environment variables `PIPER_SELENIUM_HUB_USER` and `PIPER_SELENIUM_HUB_PASSWORD`."
resources:
- name: buildDescriptor
type: stash
@ -31,10 +35,10 @@ spec:
- STAGES
- STEPS
mandatory: true
- name: modulePath
type: string
description: Define the path of the module to execute tests on.
default: "."
- name: modules
type: "[]string"
description: Define the paths of the modules to execute tests on.
default: ["."]
scope:
- PARAMETERS
- STAGES

View File

@ -170,6 +170,7 @@ public class CommonStepsTest extends BasePiperTest{
'containerSaveImage', //implementing new golang pattern without fields
'detectExecuteScan', //implementing new golang pattern without fields
'kanikoExecute', //implementing new golang pattern without fields
'karmaExecuteTests', //implementing new golang pattern without fields
'gitopsUpdateDeployment', //implementing new golang pattern without fields
'vaultRotateSecretId', //implementing new golang pattern without fields
'deployIntegrationArtifact', //implementing new golang pattern without fields

View File

@ -1,101 +0,0 @@
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.*
import static org.junit.Assert.assertThat
class KarmaExecuteTestsTest extends BasePiperTest {
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
private JenkinsEnvironmentRule environmentRule = new JenkinsEnvironmentRule(this)
private ExpectedException thrown = ExpectedException.none()
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(new JenkinsReadYamlRule(this))
.around(shellRule)
.around(loggingRule)
.around(environmentRule)
.around(stepRule)
.around(thrown)
def seleniumParams = [:]
@Before
void init() throws Exception {
helper.registerAllowedMethod("unstash", [String.class], { s -> return [s]})
helper.registerAllowedMethod('seleniumExecuteTests', [Map.class, Closure.class], {map, body ->
seleniumParams = map
return body()
})
}
@Test
void testDefaults() throws Exception {
stepRule.step.karmaExecuteTests(
script: nullScript,
juStabUtils: utils
)
assertThat(shellRule.shell, hasItems(
containsString("cd '.' && npm install --quiet"),
containsString("cd '.' && npm run karma")
))
assertThat(seleniumParams.dockerImage, is('node:lts-stretch'))
assertThat(seleniumParams.dockerName, is('karma'))
assertThat(seleniumParams.dockerWorkspace, is('/home/node'))
assertJobStatusSuccess()
}
@Test
void testDockerFromCustomStepConfiguration() {
def expectedImage = 'image:test'
def expectedEnvVars = ['NO_PROXY':'', 'no_proxy':'', 'env1': 'value1', 'env2': 'value2']
def expectedOptions = '--opt1=val1 --opt2=val2 --opt3'
def expectedWorkspace = '/path/to/workspace'
nullScript.commonPipelineEnvironment.configuration = [steps:[karmaExecuteTests:[
dockerImage: expectedImage,
dockerOptions: expectedOptions,
dockerEnvVars: expectedEnvVars,
dockerWorkspace: expectedWorkspace
]]]
stepRule.step.karmaExecuteTests(
script: nullScript,
juStabUtils: utils
)
assert expectedImage == seleniumParams.dockerImage
assert expectedOptions == seleniumParams.dockerOptions
assert expectedWorkspace == seleniumParams.dockerWorkspace
expectedEnvVars.each { key, value ->
assert seleniumParams.dockerEnvVars[key] == value
}
}
@Test
void testMultiModules() throws Exception {
stepRule.step.karmaExecuteTests(
script: nullScript,
juStabUtils: utils,
modules: ['./ui-trade', './ui-traderequest']
)
assertThat(shellRule.shell, hasItems(
containsString("cd './ui-trade' && npm run karma"),
containsString("cd './ui-trade' && npm install --quiet")
))
assertThat(shellRule.shell, hasItems(
containsString("cd './ui-traderequest' && npm run karma"),
containsString("cd './ui-traderequest' && npm install --quiet")
))
assertJobStatusSuccess()
}
}

View File

@ -9,124 +9,12 @@ import groovy.text.GStringTemplateEngine
import groovy.transform.Field
@Field String STEP_NAME = getClass().getName()
@Field Set GENERAL_CONFIG_KEYS = [
/**
* Map which defines per docker image the port mappings, e.g. `containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]]`.
*/
'containerPortMappings',
/** A map of environment variables to set in the container, e.g. [http_proxy:'proxy:8080']. */
'dockerEnvVars',
/** The name of the docker image that should be used. If empty, Docker is not used and the command is executed directly on the Jenkins system. */
'dockerImage',
/**
* Kubernetes only:
* Name of the container launching `dockerImage`.
* SideCar only:
* Name of the container in local network.
*/
'dockerName',
/**
* Kubernetes only:
* Specifies a dedicated user home directory for the container which will be passed as value for environment variable `HOME`.
*/
'dockerWorkspace',
/** @see dockerExecute */
'dockerOptions',
/**
* With `failOnError` the behavior in case tests fail can be defined.
* @possibleValues `true`, `false`
*/
'failOnError',
/** The command that is executed to install the test tool. */
'installCommand',
/** Define the paths of the modules to execute tests on. */
'modules',
/** The command that is executed to start the tests. */
'runCommand',
/** @see seleniumExecuteTests */
'seleniumHubCredentialsId',
/** A map of environment variables to set in the sidecar container, similar to `dockerEnvVars`. */
'sidecarEnvVars',
/** The name of the docker image of the sidecar container. If empty, no sidecar container is started. */
'sidecarImage',
/**
* as `dockerName` for the sidecar container
*/
'sidecarName',
/** Volumes that should be mounted into the sidecar container. */
'sidecarVolumeBind',
/** If specific stashes should be considered for the tests, their names need to be passed via the parameter `stashContent`. */
'stashContent'
]
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
@Field String METADATA_FILE = 'metadata/karma.yaml'
/**
* In this step the ([Karma test runner](http://karma-runner.github.io)) is executed.
*
* The step is using the `seleniumExecuteTest` step to spin up two containers in a Docker network:
*
* * a Selenium/Chrome container (`selenium/standalone-chrome`)
* * a NodeJS container (`node:lts-stretch`)
*
* In the Docker network, the containers can be referenced by the values provided in `dockerName` and `sidecarName`, the default values are `karma` and `selenium`. These values must be used in the `hostname` properties of the test configuration ([Karma](https://karma-runner.github.io/1.0/config/configuration-file.html) and [WebDriver](https://github.com/karma-runner/karma-webdriver-launcher#usage)).
*
* !!! note
* In a Kubernetes environment, the containers both need to be referenced with `localhost`.
*/
@GenerateDocumentation
void call(Map parameters = [:]) {
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
final script = checkScript(this, parameters) ?: this
def utils = parameters?.juStabUtils ?: new Utils()
String stageName = parameters.stageName ?: env.STAGE_NAME
// load default & individual configuration
Map config = ConfigurationHelper.newInstance(this)
.loadStepDefaults([:], stageName)
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, stageName, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.use()
utils.pushToSWA([step: STEP_NAME], config)
def testJobs = [:]
def options = [
script: script,
containerPortMappings: config.containerPortMappings,
dockerEnvVars: config.dockerEnvVars,
dockerImage: config.dockerImage,
dockerName: config.dockerName,
dockerWorkspace: config.dockerWorkspace,
dockerOptions: config.dockerOptions,
failOnError: config.failOnError,
seleniumHubCredentialsId: config.seleniumHubCredentialsId,
sidecarEnvVars: config.sidecarEnvVars,
sidecarImage: config.sidecarImage,
sidecarName: config.sidecarName,
sidecarVolumeBind: config.sidecarVolumeBind,
stashContent: config.stashContent
]
for(String path : config.modules){
String modulePath = path
testJobs["Karma - ${modulePath}"] = {
seleniumExecuteTests(options){
try {
sh "cd '${modulePath}' && ${config.installCommand}"
sh "cd '${modulePath}' && ${config.runCommand}"
} catch (e) {
error "[${STEP_NAME}] ERROR: The execution of the karma tests failed, see the log for details."
}
}
}
}
if(testJobs.size() == 1){
testJobs.each({ key, value -> value() })
}else{
parallel testJobs.plus([failFast: false])
}
}
List credentials = [
[type: 'usernamePassword', id: 'seleniumHubCredentialsId', env: ['PIPER_SELENIUM_HUB_USER', 'PIPER_SELENIUM_HUB_PASSWORD']],
]
final script = checkScript(this, parameters) ?: this
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
}