mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-03-03 15:02:35 +02:00
feat(uiVeri5): golang implmementation for uiVeri5ExecuteTests (#2394)
* added uiVeri5ExecuteTests step files * added confPath an regenerated step * added test for uiVeri5ExecuteTests * config modified * added groovy wrapper * ambiguous method fixed * uiveri5 wrapper * removed install command * fixed defaults * added testOptions as confPath arg * test set env * test npm install local * changed env settings * tests regenerated * go generate * fix code climate * overwrite groovy step * remove groovy wrapper go * unstash piper bin * test older node version * test piperExecuteBin * wip * wip * wip * wip * wip * wip * wip * refactored params * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * set testServerUrl as os env for uiveri5 * Update config.yml * fix naming of testServerUrl param * wip * refactored setEnv and fixed tests * wip * step param for NPM_CONFIG_PREFIX * fix runCommand * refactored step param, regenerate, docu, fix tests * fix groovy wrapper test * cleanup * add to CommonStepsTest field whitelist * fixed default pipeline environment vars * fix []string default * fix metadata.go bug * added test for docu metadata gen * fix metadata_test.go in doc gen * Update metadata_generated.go * Update metadata_generated.go * remove npm config prefix param; doc fix * remove tab * changed npm config prefix * removed groovy wrapper test * removed groovy step defaults * modify path variable * modified npm config prefix * fix error wrapper and tests * doc update * add testRepository support * wip * fix testRepository param * wip * add utils * init stash content * wip * wip * wip * add comment for deprecated parameters * fixed commonStepTest * fixed commonStepTest * added error category for testOptions failure * Update vars/uiVeri5ExecuteTests.groovy Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> * Update vars/uiVeri5ExecuteTests.groovy Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> * fix condition Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>
This commit is contained in:
parent
44788f1d3a
commit
e60bdb94a6
@ -60,6 +60,7 @@ func GetAllStepMetadata() map[string]config.StepData {
|
||||
"containerSaveImage": containerSaveImageMetadata(),
|
||||
"sonarExecuteScan": sonarExecuteScanMetadata(),
|
||||
"transportRequestUploadCTS": transportRequestUploadCTSMetadata(),
|
||||
"uiVeri5ExecuteTests": uiVeri5ExecuteTestsMetadata(),
|
||||
"vaultRotateSecretId": vaultRotateSecretIdMetadata(),
|
||||
"artifactPrepareVersion": artifactPrepareVersionMetadata(),
|
||||
"whitesourceExecuteScan": whitesourceExecuteScanMetadata(),
|
||||
|
@ -70,6 +70,7 @@ func Execute() {
|
||||
rootCmd.AddCommand(DetectExecuteScanCommand())
|
||||
rootCmd.AddCommand(HadolintExecuteCommand())
|
||||
rootCmd.AddCommand(KarmaExecuteTestsCommand())
|
||||
rootCmd.AddCommand(UiVeri5ExecuteTestsCommand())
|
||||
rootCmd.AddCommand(SonarExecuteScanCommand())
|
||||
rootCmd.AddCommand(KubernetesDeployCommand())
|
||||
rootCmd.AddCommand(XsDeployCommand())
|
||||
|
49
cmd/uiVeri5ExecuteTests.go
Normal file
49
cmd/uiVeri5ExecuteTests.go
Normal file
@ -0,0 +1,49 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func uiVeri5ExecuteTests(config uiVeri5ExecuteTestsOptions, telemetryData *telemetry.CustomData) {
|
||||
// for command execution use Command
|
||||
c := command.Command{}
|
||||
// reroute command output to logging framework
|
||||
c.Stdout(log.Writer())
|
||||
c.Stderr(log.Writer())
|
||||
|
||||
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
|
||||
err := runUIVeri5(&config, &c)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("step execution failed")
|
||||
}
|
||||
}
|
||||
|
||||
func runUIVeri5(config *uiVeri5ExecuteTestsOptions, command command.ExecRunner) error {
|
||||
envs := []string{"NPM_CONFIG_PREFIX=~/.npm-global"}
|
||||
path := "PATH=" + os.Getenv("PATH") + ":~/.npm-global/bin"
|
||||
envs = append(envs, path)
|
||||
if config.TestServerURL != "" {
|
||||
envs = append(envs, "TARGET_SERVER_URL="+config.TestServerURL)
|
||||
}
|
||||
command.SetEnv(envs)
|
||||
|
||||
installCommandTokens := strings.Split(config.InstallCommand, " ")
|
||||
if err := command.RunExecutable(installCommandTokens[0], installCommandTokens[1:]...); err != nil {
|
||||
return errors.Wrapf(err, "failed to execute install command: %v", config.InstallCommand)
|
||||
}
|
||||
|
||||
if config.TestOptions != "" {
|
||||
log.SetErrorCategory(log.ErrorConfiguration)
|
||||
return errors.Errorf("parameter testOptions no longer supported, please use runOptions parameter instead.")
|
||||
}
|
||||
if err := command.RunExecutable(config.RunCommand, config.RunOptions...); err != nil {
|
||||
return errors.Wrapf(err, "failed to execute run command: %v %v", config.RunCommand, config.RunOptions)
|
||||
}
|
||||
return nil
|
||||
}
|
154
cmd/uiVeri5ExecuteTests_generated.go
Normal file
154
cmd/uiVeri5ExecuteTests_generated.go
Normal file
@ -0,0 +1,154 @@
|
||||
// Code generated by piper's step-generator. DO NOT EDIT.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type uiVeri5ExecuteTestsOptions struct {
|
||||
InstallCommand string `json:"installCommand,omitempty"`
|
||||
RunCommand string `json:"runCommand,omitempty"`
|
||||
RunOptions []string `json:"runOptions,omitempty"`
|
||||
TestOptions string `json:"testOptions,omitempty"`
|
||||
TestServerURL string `json:"testServerUrl,omitempty"`
|
||||
}
|
||||
|
||||
// UiVeri5ExecuteTestsCommand Executes UI5 e2e tests using uiVeri5
|
||||
func UiVeri5ExecuteTestsCommand() *cobra.Command {
|
||||
const STEP_NAME = "uiVeri5ExecuteTests"
|
||||
|
||||
metadata := uiVeri5ExecuteTestsMetadata()
|
||||
var stepConfig uiVeri5ExecuteTestsOptions
|
||||
var startTime time.Time
|
||||
|
||||
var createUiVeri5ExecuteTestsCmd = &cobra.Command{
|
||||
Use: STEP_NAME,
|
||||
Short: "Executes UI5 e2e tests using uiVeri5",
|
||||
Long: `In this step the ([UIVeri5 tests](https://github.com/SAP/ui5-uiveri5)) are executed.`,
|
||||
PreRunE: func(cmd *cobra.Command, _ []string) error {
|
||||
startTime = time.Now()
|
||||
log.SetStepName(STEP_NAME)
|
||||
log.SetVerbose(GeneralConfig.Verbose)
|
||||
|
||||
path, _ := os.Getwd()
|
||||
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
|
||||
log.RegisterHook(fatalHook)
|
||||
|
||||
err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
|
||||
if err != nil {
|
||||
log.SetErrorCategory(log.ErrorConfiguration)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
|
||||
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
|
||||
log.RegisterHook(&sentryHook)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
telemetryData := telemetry.CustomData{}
|
||||
telemetryData.ErrorCode = "1"
|
||||
handler := func() {
|
||||
config.RemoveVaultSecretFiles()
|
||||
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
|
||||
telemetryData.ErrorCategory = log.GetErrorCategory().String()
|
||||
telemetry.Send(&telemetryData)
|
||||
}
|
||||
log.DeferExitHandler(handler)
|
||||
defer handler()
|
||||
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
|
||||
uiVeri5ExecuteTests(stepConfig, &telemetryData)
|
||||
telemetryData.ErrorCode = "0"
|
||||
log.Entry().Info("SUCCESS")
|
||||
},
|
||||
}
|
||||
|
||||
addUiVeri5ExecuteTestsFlags(createUiVeri5ExecuteTestsCmd, &stepConfig)
|
||||
return createUiVeri5ExecuteTestsCmd
|
||||
}
|
||||
|
||||
func addUiVeri5ExecuteTestsFlags(cmd *cobra.Command, stepConfig *uiVeri5ExecuteTestsOptions) {
|
||||
cmd.Flags().StringVar(&stepConfig.InstallCommand, "installCommand", `npm install @ui5/uiveri5 --global --quiet`, "The command that is executed to install the uiveri5 test tool.")
|
||||
cmd.Flags().StringVar(&stepConfig.RunCommand, "runCommand", `/home/node/.npm-global/bin/uiveri5`, "The command that is executed to start the tests.")
|
||||
cmd.Flags().StringSliceVar(&stepConfig.RunOptions, "runOptions", []string{`--seleniumAddress='http://localhost:4444/wd/hub'`}, "Options to append to the runCommand, last parameter has to be path to conf.js (default if missing: ./conf.js).")
|
||||
cmd.Flags().StringVar(&stepConfig.TestOptions, "testOptions", os.Getenv("PIPER_testOptions"), "Deprecated and will result in an error if set. Please use runOptions instead.")
|
||||
cmd.Flags().StringVar(&stepConfig.TestServerURL, "testServerUrl", os.Getenv("PIPER_testServerUrl"), "URL pointing to the deployment.")
|
||||
|
||||
cmd.MarkFlagRequired("installCommand")
|
||||
cmd.MarkFlagRequired("runCommand")
|
||||
cmd.MarkFlagRequired("runOptions")
|
||||
}
|
||||
|
||||
// retrieve step metadata
|
||||
func uiVeri5ExecuteTestsMetadata() config.StepData {
|
||||
var theMetaData = config.StepData{
|
||||
Metadata: config.StepMetadata{
|
||||
Name: "uiVeri5ExecuteTests",
|
||||
Aliases: []config.Alias{},
|
||||
Description: "Executes UI5 e2e tests using uiVeri5",
|
||||
},
|
||||
Spec: config.StepSpec{
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "installCommand",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "runCommand",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "runOptions",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "testOptions",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "testServerUrl",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
Containers: []config.Container{
|
||||
{Name: "uiVeri5", Image: "node:lts-stretch", EnvVars: []config.EnvVar{{Name: "no_proxy", Value: "localhost,selenium,$no_proxy"}, {Name: "NO_PROXY", Value: "localhost,selenium,$NO_PROXY"}}, WorkingDir: "/home/node"},
|
||||
},
|
||||
Sidecars: []config.Container{
|
||||
{Name: "selenium", Image: "selenium/standalone-chrome", EnvVars: []config.EnvVar{{Name: "NO_PROXY", Value: "localhost,selenium,$NO_PROXY"}, {Name: "no_proxy", Value: "localhost,selenium,$no_proxy"}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
return theMetaData
|
||||
}
|
17
cmd/uiVeri5ExecuteTests_generated_test.go
Normal file
17
cmd/uiVeri5ExecuteTests_generated_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUiVeri5ExecuteTestsCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCmd := UiVeri5ExecuteTestsCommand()
|
||||
|
||||
// only high level testing performed - details are tested in step generation procedure
|
||||
assert.Equal(t, "uiVeri5ExecuteTests", testCmd.Use, "command name incorrect")
|
||||
|
||||
}
|
52
cmd/uiVeri5ExecuteTests_test.go
Normal file
52
cmd/uiVeri5ExecuteTests_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/mock"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRunUIVeri5(t *testing.T) {
|
||||
t.Run("success case", func(t *testing.T) {
|
||||
opts := &uiVeri5ExecuteTestsOptions{
|
||||
InstallCommand: "npm install ui5/uiveri5",
|
||||
RunCommand: "uiveri5",
|
||||
RunOptions: []string{"conf.js"},
|
||||
TestServerURL: "http://path/to/deployment",
|
||||
}
|
||||
|
||||
e := mock.ExecMockRunner{}
|
||||
runUIVeri5(opts, &e)
|
||||
|
||||
assert.Equal(t, e.Env[0], "NPM_CONFIG_PREFIX=~/.npm-global", "NPM_CONFIG_PREFIX not set as expected")
|
||||
assert.Contains(t, e.Env[1], "PATH", "PATH not in env list")
|
||||
assert.Equal(t, e.Env[2], "TARGET_SERVER_URL=http://path/to/deployment", "TARGET_SERVER_URL not set as expected")
|
||||
|
||||
assert.Equal(t, e.Calls[0], mock.ExecCall{Exec: "npm", Params: []string{"install", "ui5/uiveri5"}}, "install command/params incorrect")
|
||||
|
||||
assert.Equal(t, e.Calls[1], mock.ExecCall{Exec: "uiveri5", Params: []string{"conf.js"}}, "run command/params incorrect")
|
||||
|
||||
})
|
||||
|
||||
t.Run("error case install command", func(t *testing.T) {
|
||||
wantError := "failed to execute install command: fail install test: error case"
|
||||
|
||||
opts := &uiVeri5ExecuteTestsOptions{InstallCommand: "fail install test", RunCommand: "uiveri5"}
|
||||
|
||||
e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"fail install test": errors.New("error case")}}
|
||||
err := runUIVeri5(opts, &e)
|
||||
assert.EqualErrorf(t, err, wantError, "expected comman to exit with error")
|
||||
})
|
||||
|
||||
t.Run("error case run command", func(t *testing.T) {
|
||||
wantError := "failed to execute run command: fail uiveri5 [testParam]: error case"
|
||||
|
||||
opts := &uiVeri5ExecuteTestsOptions{InstallCommand: "npm install ui5/uiveri5", RunCommand: "fail uiveri5", RunOptions: []string{"testParam"}}
|
||||
|
||||
e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"fail uiveri5": errors.New("error case")}}
|
||||
err := runUIVeri5(opts, &e)
|
||||
assert.EqualErrorf(t, err, wantError, "expected comman to exit with error")
|
||||
})
|
||||
}
|
@ -12,8 +12,12 @@
|
||||
|
||||
## Exceptions
|
||||
|
||||
The parameter `testOptions` is deprecated and is replaced by `runOptions`.
|
||||
|
||||
Using the `runOptions` parameter the 'seleniumAddress' for uiveri5 can be set. For jenkins on kubernetes the host is 'localhost', in other environments, e.g. native jenkins installations, the host can be set to 'selenium'.
|
||||
|
||||
If you see an error like `fatal: Not a git repository (or any parent up to mount point /home/jenkins)` it is likely that your test description cannot be found.<br />
|
||||
Please make sure to point parameter `testOptions` to your `conf.js` file like `testOptions: './path/to/my/tests/conf.js'`
|
||||
Please make sure to point parameter `runOptions` to your `conf.js` file like `runOptions: ['./path/to/my/tests/conf.js']`
|
||||
|
||||
## Examples
|
||||
|
||||
@ -65,7 +69,7 @@ withCredentials([usernamePassword(
|
||||
passwordVariable: 'password',
|
||||
usernameVariable: 'username'
|
||||
)]) {
|
||||
uiVeri5ExecuteTests script: this, testOptions: "./uiveri5/conf.js --params.user=\${username} --params.pass=\${password}"
|
||||
uiVeri5ExecuteTests script: this, runOptions: ["./uiveri5/conf.js", "--params.user=\${username}", "--params.pass=\${password}"]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -41,7 +41,7 @@ func adjustMandatoryFlags(stepMetadata *config.StepData) {
|
||||
if parameter.Mandatory {
|
||||
if parameter.Default == nil ||
|
||||
parameter.Default == "" ||
|
||||
parameter.Type == "[]string" && len(parameter.Default.([]string)) == 0 {
|
||||
parameter.Type == "[]string" && interfaceArrayLength(parameter.Default) == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("Changing mandatory flag to '%v' for parameter '%s', default value available '%v'.\n", false, parameter.Name, parameter.Default)
|
||||
@ -75,3 +75,15 @@ func applyCustomDefaultValues(stepMetadata *config.StepData, stepConfiguration c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check length only if interface type is a slice
|
||||
func interfaceArrayLength(i interface{}) int {
|
||||
switch i.(type) {
|
||||
case []string:
|
||||
return len(i.([]string))
|
||||
case []interface{}:
|
||||
return len(i.([]interface{}))
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
@ -76,3 +76,47 @@ func Test_adjustMandatoryFlags(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_interfaceArrayLength(t *testing.T) {
|
||||
type args struct {
|
||||
i interface{}
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
}{
|
||||
{
|
||||
name: "empty type",
|
||||
args: args{},
|
||||
want: -1,
|
||||
},
|
||||
{
|
||||
name: "string type",
|
||||
args: args{"string"},
|
||||
want: -1,
|
||||
},
|
||||
{
|
||||
name: "empty array type",
|
||||
args: args{[]interface{}{}},
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "string array type",
|
||||
args: args{[]interface{}{"string1", "string1"}},
|
||||
want: 2,
|
||||
},
|
||||
{
|
||||
name: "string array type",
|
||||
args: args{[]string{"string1", "string1"}},
|
||||
want: 2,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := interfaceArrayLength(tt.args.i); got != tt.want {
|
||||
t.Errorf("interfaceArrayLength() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -600,16 +600,6 @@ steps:
|
||||
verbose: false
|
||||
transportRequestRelease:
|
||||
verbose: false
|
||||
uiVeri5ExecuteTests:
|
||||
failOnError: false
|
||||
dockerEnvVars: {}
|
||||
installCommand: 'npm install @ui5/uiveri5 --global --quiet'
|
||||
seleniumPort: 4444
|
||||
stashContent:
|
||||
- 'buildDescriptor'
|
||||
- 'tests'
|
||||
testOptions: ''
|
||||
runCommand: "uiveri5 --seleniumAddress='http://${config.seleniumHost}:${config.seleniumPort}/wd/hub'"
|
||||
writeTemporaryCredentials:
|
||||
credentialsDirectories:
|
||||
- './'
|
||||
|
80
resources/metadata/uiVeri5ExecuteTests.yaml
Normal file
80
resources/metadata/uiVeri5ExecuteTests.yaml
Normal file
@ -0,0 +1,80 @@
|
||||
metadata:
|
||||
name: uiVeri5ExecuteTests
|
||||
description: Executes UI5 e2e tests using uiVeri5
|
||||
longDescription: |
|
||||
In this step the ([UIVeri5 tests](https://github.com/SAP/ui5-uiveri5)) are executed.
|
||||
|
||||
# The step is using `dockerExecute` 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 `uiVeri5` and `selenium`.
|
||||
# !!! note
|
||||
# In a Kubernetes environment, the containers both need to be referenced with `localhost`.
|
||||
spec:
|
||||
inputs:
|
||||
params:
|
||||
- name: installCommand
|
||||
type: string
|
||||
description: The command that is executed to install the uiveri5 test tool.
|
||||
default: npm install @ui5/uiveri5 --global --quiet
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
mandatory: true
|
||||
- name: runCommand
|
||||
type: string
|
||||
description: "The command that is executed to start the tests."
|
||||
default: /home/node/.npm-global/bin/uiveri5
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
mandatory: true
|
||||
- name: runOptions
|
||||
type: "[]string"
|
||||
description: "Options to append to the runCommand, last parameter has to be path to conf.js (default if missing: ./conf.js)."
|
||||
default: ["--seleniumAddress='http://localhost:4444/wd/hub'"]
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
mandatory: true
|
||||
- name: testOptions
|
||||
type: string
|
||||
description: "Deprecated and will result in an error if set. Please use runOptions instead."
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: testServerUrl
|
||||
type: string
|
||||
description: "URL pointing to the deployment."
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
containers:
|
||||
- name: uiVeri5
|
||||
image: node:lts-stretch
|
||||
env:
|
||||
- name: no_proxy
|
||||
value: localhost,selenium,$no_proxy
|
||||
- name: NO_PROXY
|
||||
value: localhost,selenium,$NO_PROXY
|
||||
workingDir: /home/node
|
||||
sidecars:
|
||||
- image: selenium/standalone-chrome
|
||||
name: selenium
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- mountPath: /dev/shm
|
||||
name: dev-shm
|
||||
env:
|
||||
- name: "NO_PROXY"
|
||||
value: "localhost,selenium,$NO_PROXY"
|
||||
- name: "no_proxy"
|
||||
value: "localhost,selenium,$no_proxy"
|
@ -170,7 +170,9 @@ public class CommonStepsTest extends BasePiperTest{
|
||||
'kanikoExecute', //implementing new golang pattern without fields
|
||||
'gitopsUpdateDeployment', //implementing new golang pattern without fields
|
||||
'vaultRotateSecretId', //implementing new golang pattern without fields
|
||||
'integrationArtifactDeploy', //implementing new golang pattern without fields
|
||||
'deployIntegrationArtifact', //implementing new golang pattern without fields
|
||||
'uiVeri5ExecuteTests', //implementing new golang pattern without fields
|
||||
'integrationArtifactDeploy' //implementing new golang pattern without fields
|
||||
]
|
||||
|
||||
@Test
|
||||
|
@ -1,186 +0,0 @@
|
||||
import static org.hamcrest.Matchers.*
|
||||
|
||||
import com.sap.piper.Utils
|
||||
|
||||
import hudson.AbortException
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.RuleChain
|
||||
import org.junit.rules.ExpectedException
|
||||
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
import util.BasePiperTest
|
||||
import util.JenkinsDockerExecuteRule
|
||||
import util.JenkinsLoggingRule
|
||||
import util.JenkinsReadYamlRule
|
||||
import util.JenkinsStepRule
|
||||
import util.Rules
|
||||
|
||||
class UiVeri5ExecuteTestsTest extends BasePiperTest {
|
||||
private ExpectedException thrown = ExpectedException.none()
|
||||
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
|
||||
private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
|
||||
private JenkinsDockerExecuteRule dockerRule = new JenkinsDockerExecuteRule(this)
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(thrown)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(dockerRule)
|
||||
.around(loggingRule)
|
||||
.around(stepRule)
|
||||
|
||||
def gitParams = [:]
|
||||
def shellCommands = []
|
||||
def seleniumMap = [:]
|
||||
|
||||
class MockBuild {
|
||||
MockBuild(){}
|
||||
def getRootDir(){
|
||||
return new MockPath()
|
||||
}
|
||||
class MockPath {
|
||||
MockPath(){}
|
||||
// return default
|
||||
String getAbsolutePath(){
|
||||
return 'myPath'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
|
||||
binding.setVariable('currentBuild', [
|
||||
result: 'SUCCESS',
|
||||
rawBuild: new MockBuild()
|
||||
])
|
||||
|
||||
helper.registerAllowedMethod("git", [Map.class], { map -> gitParams = map})
|
||||
helper.registerAllowedMethod("stash", [String.class], null)
|
||||
helper.registerAllowedMethod("unstash", [String.class], { s -> return [s]})
|
||||
helper.registerAllowedMethod("sh", [String.class], { s ->
|
||||
if (s.contains('failure')) throw new RuntimeException('Test Error')
|
||||
shellCommands.add(s.toString())
|
||||
})
|
||||
helper.registerAllowedMethod("sh", [Map.class], { map ->
|
||||
return 'available'
|
||||
})
|
||||
helper.registerAllowedMethod('seleniumExecuteTests', [Map.class, Closure.class], { m, body ->
|
||||
seleniumMap = m
|
||||
return body()
|
||||
})
|
||||
Utils.metaClass.echo = { def m -> }
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Utils.metaClass = null
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefault() throws Exception {
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
])
|
||||
// asserts
|
||||
assertThat(shellCommands, hasItem(containsString('npm install @ui5/uiveri5 --global --quiet')))
|
||||
assertThat(shellCommands, hasItem(containsString('uiveri5 --seleniumAddress=\'http://selenium:4444/wd/hub\'')))
|
||||
assertThat(seleniumMap.dockerImage, isEmptyOrNullString())
|
||||
assertThat(seleniumMap.dockerWorkspace, isEmptyOrNullString())
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultOnK8s() throws Exception {
|
||||
// prepare
|
||||
binding.variables.env.ON_K8S = 'true'
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
])
|
||||
// asserts
|
||||
assertThat(shellCommands, hasItem(containsString('npm install @ui5/uiveri5 --global --quiet')))
|
||||
assertThat(shellCommands, hasItem(containsString('uiveri5 --seleniumAddress=\'http://localhost:4444/wd/hub\'')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithCustomSidecar() throws Exception {
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
sidecarEnvVars: [myEnv: 'testValue'],
|
||||
sidecarImage: 'myImage'
|
||||
])
|
||||
// asserts
|
||||
assertThat(seleniumMap.sidecarImage, is('myImage'))
|
||||
assertThat(seleniumMap.sidecarEnvVars.myEnv, is('testValue'))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithTestRepository() throws Exception {
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
testRepository: 'git@myGitUrl'
|
||||
])
|
||||
// asserts
|
||||
assertThat(seleniumMap, hasKey('stashContent'))
|
||||
assertThat(seleniumMap.stashContent, hasItem(startsWith('testContent-')))
|
||||
assertThat(gitParams, hasEntry('url', 'git@myGitUrl'))
|
||||
assertThat(gitParams, not(hasKey('credentialsId')))
|
||||
assertThat(gitParams, not(hasKey('branch')))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithTestRepositoryWithGitBranchAndCredentials() throws Exception {
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
script: nullScript,
|
||||
juStabUtils: utils,
|
||||
testRepository: 'git@myGitUrl',
|
||||
gitSshKeyCredentialsId: 'myCredentials',
|
||||
gitBranch: 'myBranch'
|
||||
])
|
||||
// asserts
|
||||
assertThat(gitParams, hasEntry('url', 'git@myGitUrl'))
|
||||
assertThat(gitParams, hasEntry('credentialsId', 'myCredentials'))
|
||||
assertThat(gitParams, hasEntry('branch', 'myBranch'))
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithFailOnError() throws Exception {
|
||||
thrown.expect(AbortException)
|
||||
thrown.expectMessage('ERROR: The execution of the uiveri5 tests failed, see the log for details.')
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
juStabUtils: utils,
|
||||
failOnError: true,
|
||||
testOptions: 'failure',
|
||||
script: nullScript
|
||||
])
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithoutFailOnError() throws Exception {
|
||||
// execute test
|
||||
stepRule.step.uiVeri5ExecuteTests([
|
||||
juStabUtils: utils,
|
||||
testOptions: 'failure',
|
||||
script: nullScript
|
||||
])
|
||||
// asserts
|
||||
assertJobStatusSuccess()
|
||||
}
|
||||
}
|
@ -1,147 +1,43 @@
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.GitUtils
|
||||
import com.sap.piper.Utils
|
||||
|
||||
import groovy.text.GStringTemplateEngine
|
||||
import groovy.transform.Field
|
||||
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
@Field String STEP_NAME = getClass().getName()
|
||||
@Field String METADATA_FILE = 'metadata/uiVeri5ExecuteTests.yaml'
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = [
|
||||
/** @see seleniumExecuteTests */
|
||||
'gitSshKeyCredentialsId'
|
||||
]
|
||||
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus([
|
||||
/** @see dockerExecute */
|
||||
'dockerEnvVars',
|
||||
/** @see dockerExecute */
|
||||
'dockerImage',
|
||||
/** @see dockerExecute */
|
||||
'dockerWorkspace',
|
||||
/**
|
||||
* With `failOnError` the behavior in case tests fail can be defined.
|
||||
* @possibleValues `true`, `false`
|
||||
*/
|
||||
'failOnError',
|
||||
/** @see seleniumExecuteTests */
|
||||
'gitBranch',
|
||||
/**
|
||||
* The command that is executed to install the test tool.
|
||||
*/
|
||||
'installCommand',
|
||||
/**
|
||||
* The command that is executed to start the tests.
|
||||
*/
|
||||
'runCommand',
|
||||
/**
|
||||
* The host of the selenium hub, this is set automatically to `localhost` in a Kubernetes environment (determined by the `ON_K8S` environment variable) of to `selenium` in any other case. The value is only needed for the `runCommand`.
|
||||
*/
|
||||
'seleniumHost',
|
||||
/** @see seleniumExecuteTests */
|
||||
'seleniumHubCredentialsId',
|
||||
/**
|
||||
* The port of the selenium hub. The value is only needed for the `runCommand`.
|
||||
*/
|
||||
'seleniumPort',
|
||||
/** @see dockerExecute */
|
||||
'sidecarEnvVars',
|
||||
/** @see dockerExecute */
|
||||
'sidecarImage',
|
||||
/** @see dockerExecute */
|
||||
'stashContent',
|
||||
/**
|
||||
* This allows to set specific options for the UIVeri5 execution. Details can be found [in the UIVeri5 documentation](https://github.com/SAP/ui5-uiveri5/blob/master/docs/config/config.md#configuration).
|
||||
*/
|
||||
'testOptions',
|
||||
/** @see seleniumExecuteTests */
|
||||
'testRepository',
|
||||
/**
|
||||
* The `testServerUrl` is passed as environment variable `TARGET_SERVER_URL` to the test execution.
|
||||
* The tests should read the host information from this environment variable in order to be infrastructure agnostic.
|
||||
*/
|
||||
'testServerUrl'
|
||||
])
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
/**
|
||||
* With this step [UIVeri5](https://github.com/SAP/ui5-uiveri5) tests can be executed.
|
||||
/*
|
||||
* Parameters read from config for backwards compatibility of groovy wrapper step:
|
||||
*
|
||||
* UIVeri5 describes following benefits on its GitHub page:
|
||||
*
|
||||
* * Automatic synchronization with UI5 app rendering so there is no need to add waits and sleeps to your test. Tests are reliable by design.
|
||||
* * Tests are written in synchronous manner, no callbacks, no promise chaining so are really simple to write and maintain.
|
||||
* * Full power of webdriverjs, protractor and jasmine - deferred selectors, custom matchers, custom locators.
|
||||
* * Control locators (OPA5 declarative matchers) allow locating and interacting with UI5 controls.
|
||||
* * Does not depend on testability support in applications - works with autorefreshing views, resizing elements, animated transitions.
|
||||
* * Declarative authentications - authentication flow over OAuth2 providers, etc.
|
||||
* * Console operation, CI ready, fully configurable, no need for java (coming soon) or IDE.
|
||||
* * Covers full ui5 browser matrix - Chrome,Firefox,IE,Edge,Safari,iOS,Android.
|
||||
* * Open-source, modify to suite your specific neeeds.
|
||||
*
|
||||
* !!! note "Browser Matrix"
|
||||
* With this step and the underlying Docker image ([selenium/standalone-chrome](https://github.com/SeleniumHQ/docker-selenium/tree/master/StandaloneChrome)) only Chrome tests are possible.
|
||||
*
|
||||
* Testing of further browsers can be done with using a custom Docker image.
|
||||
* testRepository, gitBranch, gitSshKeyCredentialsId used for test repository loading
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) {
|
||||
def script = checkScript(this, parameters) ?: this
|
||||
def utils = parameters.juStabUtils ?: new Utils()
|
||||
String stageName = parameters.stageName ?: env.STAGE_NAME
|
||||
@Field Set CONFIG_KEYS = [
|
||||
"gitBranch",
|
||||
"gitSshKeyCredentialsId",
|
||||
"testRepository",
|
||||
]
|
||||
|
||||
// load default & individual configuration
|
||||
Map config = ConfigurationHelper.newInstance(this)
|
||||
void call(Map parameters = [:]) {
|
||||
final script = checkScript(this, parameters) ?: this
|
||||
String stageName = parameters.stageName ?: env.STAGE_NAME
|
||||
def utils = parameters.juStabUtils ?: new Utils()
|
||||
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)
|
||||
.addIfEmpty('seleniumHost', isKubernetes()?'localhost':'selenium')
|
||||
.mixinGeneralConfig(script.commonPipelineEnvironment, CONFIG_KEYS)
|
||||
.mixinStepConfig(script.commonPipelineEnvironment, CONFIG_KEYS)
|
||||
.mixinStageConfig(script.commonPipelineEnvironment, stageName, CONFIG_KEYS)
|
||||
.mixin(parameters, CONFIG_KEYS)
|
||||
.use()
|
||||
|
||||
utils.pushToSWA([
|
||||
step: STEP_NAME,
|
||||
stepParamKey1: 'scriptMissing',
|
||||
stepParam1: parameters?.script == null
|
||||
], config)
|
||||
|
||||
config.stashContent = config.testRepository ? [GitUtils.handleTestRepository(this, config)] : utils.unstashAll(config.stashContent)
|
||||
config.installCommand = GStringTemplateEngine.newInstance().createTemplate(config.installCommand).make([config: config]).toString()
|
||||
config.runCommand = GStringTemplateEngine.newInstance().createTemplate(config.runCommand).make([config: config]).toString()
|
||||
config.dockerEnvVars.TARGET_SERVER_URL = config.dockerEnvVars.TARGET_SERVER_URL ?: config.testServerUrl
|
||||
|
||||
seleniumExecuteTests(
|
||||
script: script,
|
||||
buildTool: 'npm',
|
||||
dockerEnvVars: config.dockerEnvVars,
|
||||
dockerImage: config.dockerImage,
|
||||
dockerName: config.dockerName,
|
||||
dockerWorkspace: config.dockerWorkspace,
|
||||
seleniumHubCredentialsId: config.seleniumHubCredentialsId,
|
||||
sidecarEnvVars: config.sidecarEnvVars,
|
||||
sidecarImage: config.sidecarImage,
|
||||
stashContent: config.stashContent
|
||||
) {
|
||||
sh returnStatus: true, script: """
|
||||
node --version
|
||||
npm --version
|
||||
"""
|
||||
try {
|
||||
sh "NPM_CONFIG_PREFIX=~/.npm-global ${config.installCommand}"
|
||||
sh "PATH=\$PATH:~/.npm-global/bin ${config.runCommand} ${config.testOptions}"
|
||||
} catch (err) {
|
||||
echo "[${STEP_NAME}] Test execution failed"
|
||||
script.currentBuild.result = 'UNSTABLE'
|
||||
if (config.failOnError) error "[${STEP_NAME}] ERROR: The execution of the uiveri5 tests failed, see the log for details."
|
||||
}
|
||||
}
|
||||
if (parameters.testRepository || config.testRepository ) {
|
||||
parameters.stashContent = GitUtils.handleTestRepository(this, [gitBranch: config.gitBranch, gitSshKeyCredentialsId: config.gitSshKeyCredentialsId, testRepository: config.testRepository])
|
||||
}
|
||||
}
|
||||
|
||||
boolean isKubernetes() {
|
||||
return Boolean.valueOf(env.ON_K8S)
|
||||
List credentials = [
|
||||
[type: 'usernamePassword', id: 'seleniumHubCredentialsId', env: ['PIPER_SELENIUM_HUB_USER', 'PIPER_SELENIUM_HUB_PASSWORD']],
|
||||
]
|
||||
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user