You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +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:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							d04a7c2eb3
						
					
				
				
					commit
					61f4c5245a
				
			| @@ -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") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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{}, | ||||
| 					}, | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
| } | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user