Jenkins高级篇之Pipeline实践篇-6-Selenium和Jenkins持续集成-pipeline参数化构建selenium自动化测试

释放双眼,带上耳机,听听看~!

       这篇来思考下如何写一个方法,可以修改config.properties文件里面的属性。加入这个方法可以根据key修改value,那么我们就可以通过jenkins上变量,让用户输入,来修改config.properties文件里面的值。例如测试服务器地址和浏览器类型的名称。如果用户在Jenkins界面填写浏览器是chrome,那么我们就修改config.properties里面的browser=chrome,如果用户填写的是firefox,那么我们就在启动selenium测试之前去修改browser=firefox。这样,灵活的控制参数,就达到了我们第一个需求。

1.根据Java的方法

我们知道grooy是可以无缝执行java代码,我也写了一个java的代码,放在pipleline/selenium.groovy文件里,结果我在测试的时候,报了一个错误,这个需要jenkins管理员去approve这个脚本的执行,但是我的jenkins环境上没有这个approve的相关的script,很神奇。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1import hudson.model.*;
2import java.io.FileInputStream;
3import java.io.FileNotFoundException;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.util.Properties;
7
8
9def setKeyValue(key, value, file_path) {
10    Properties prop = new Properties()
11    try {
12        prop.load(new FileInputStream(file_path))
13    }catch (FileNotFoundException e){
14        e.printStackTrace()
15    }catch (IOException e) {
16        e.printStackTrace()
17    }
18    
19    // write into file
20    try {
21        prop.setProperty(key, value)
22      FileOutputStream fos = new FileOutputStream(file_path)
23        prop.store(fos, null)
24        fos.close()
25    }catch (FileNotFoundException e){
26        e.printStackTrace()
27    }catch (IOException e) {
28        e.printStackTrace()
29    }
30}
31
32return this;
33

结果测试下,报了一个沙箱错误:


1
2
1ERROR: Error met:org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use new java.util.Properties
2

其实,这个类似错误,我在工作中也遇到过,一般来说管理员去点击批准这个脚本执行就可以。我的环境,在升级一个script security相关的插件之后,连脚本批准入口都不显示了,很神奇。只好换一种思路去写代码了。

2.Pipeline自带的readFile和writeFile

我的思路是这样的,先通过readFile方法获取到原来文件的内容,返回是一个字符串对象。然后根据换行符把字符串对象给切片,拿到一个list对象,遍历这个list,用if判断,根据Key找到这行,然后改写这行。由于这我们只是在内存改写,所以需要提前定义一个list对象来把改写和没有改写的都给add到新list,然后定义一个空字符串,遍历新list,每次拼接一个list元素都加上换行符。这样得到字符串就是一个完整内容,然后把这个内容利用writeFile方法写回到原来的config文件。

具体代码是这样的。

selenium_jenkins.groovy文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
1import hudson.model.*;
2
3pipeline{
4
5    agent any
6    parameters {
7        string(name: 'BROWSER_TYPE', defaultValue: 'chrome', description: 'Type a browser type, should be chrome/firefox')
8        string(name: 'TEST_SERVER_URL', defaultValue: '', description: 'Type the test server url')
9        string(name: 'NODE', defaultValue: 'win-anthony-demo', description: 'Please choose a windows node to execute this job.')
10    }
11    
12  stages{
13      stage("Initialization"){
14          steps{
15              script{
16                  browser = BROWSER_TYPE?.trim()
17                  test_url = TEST_SERVER_URL?.trim()
18                  win_node = NODE?.trim()
19              }
20          }
21      }
22
23      stage("Git Checkout"){
24          steps{
25              script{
26                  node(win_node) {
27                       checkout([$class: 'GitSCM', branches: [[name: '*/master']],
28                          userRemoteConfigs: [[credentialsId: '6f4fa66c-eb02-46dc-a4b3-3a232be5ef6e',
29                          url: 'https://github.com/QAAutomationLearn/JavaAutomationFramework.git']]])
30                  }
31              }
32          }
33      }
34     
35        stage("Set key value"){
36          steps{
37              script{
38                  node(win_node){
39                      selenium_test = load env.WORKSPACE + "\\pipeline\\selenium.groovy"
40                      config_file = env.WORKSPACE + "\\Configs\\config.properties"
41                      try{
42                          selenium_test.setKeyValue2("browser", "abc123", config_file)
43                          file_content = readFile config_file
44                            println file_content
45                      }catch (Exception e) {
46                          error("Error met:" + e)
47                      }
48                  }
49              }
50          }
51      }
52     
53      stage("Run Selenium Test"){
54          steps{
55              script{
56                  node(win_node){
57                      println "Here will start to run selenium test."
58                  }
59              }
60          }
61      }
62  }
63
64
65
66}
67
68

selenium.groovy文件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
1import hudson.model.*;
2import java.io.FileInputStream;
3import java.io.FileNotFoundException;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.util.Properties;
7
8
9def setKeyValue(key, value, file_path) {
10    Properties prop = new Properties()
11    try {
12        prop.load(new FileInputStream(file_path))
13    }catch (FileNotFoundException e){
14        e.printStackTrace()
15    }catch (IOException e) {
16        e.printStackTrace()
17    }
18    
19    // write into file
20    try {
21        prop.setProperty(key, value)
22      FileOutputStream fos = new FileOutputStream(file_path)
23        prop.store(fos, null)
24        fos.close()
25    }catch (FileNotFoundException e){
26        e.printStackTrace()
27    }catch (IOException e) {
28        e.printStackTrace()
29    }
30}
31
32def setKeyValue2(key, value, file_path) {
33    // read file, get string object
34    file_content_old = readFile file_path
35    println file_content_old
36    //遍历每一行,判断,然后替换字符串
37    lines = file_content_old.tokenize("\n")
38    new_lines = []
39    lines.each { line ->
40        if(line.trim().startsWith(key)) {
41            line = key + "=" + value
42            new_lines.add(line)
43        }else {
44            new_lines.add(line)
45        }
46    }
47    // write into file
48    file_content_new = ""
49    new_lines.each{line ->
50        file_content_new += line + "\n"
51    }
52
53    writeFile file: file_path, text: file_content_new, encoding: "UTF-8"
54}
55return this;
56

这里看第二个方法是我的思路,虽然比较啰嗦,但是实现了这个修改文件的需求。

测试结果看看是否把browser = chrome 改成browser = abc123


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1[Pipeline] readFile
2[Pipeline] echo
3baseURL=http://demo.guru99.com/v4/index.php
4# https://www.utest.com  backup website
5userName=mngr169501
6password=sYhYtUd
7
8# browser driver path
9firefoxpath=./Drivers\\geckodriver.exe
10chromepath=./Drivers\\chromedriver.exe
11
12# browser instance
13# the browser vlaue will only be firefox or chrome here
14browser=chrome
15
16
17[Pipeline] writeFile
18[Pipeline] readFile
19[Pipeline] echo
20baseURL=http://demo.guru99.com/v4/index.php
21# https://www.utest.com  backup website
22userName=mngr169501
23password=sYhYtUd
24
25# browser driver path
26firefoxpath=./Drivers\\geckodriver.exe
27chromepath=./Drivers\\chromedriver.exe
28
29# browser instance
30# the browser vlaue will only be firefox or chrome here
31browser=abc123
32
33
34[Pipeline] }
35[Pipeline] // node
36

你如果对日志不放心,你可以去你拉取之后代码路径去看看是否修改了,修改的对不对。

接下来,
我把github里面config.properties 中browser的值改成firefox,然后我通过pipeline代码去改成chrome,来跑一个集成测试,看看行不行,测试环境URL就无法改,这个没有第二套同样产品的地址,这个就留个你们自己项目上的测试环境和生产环境,自己试一下。

提交之后,两个文件代码如下


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
1import hudson.model.*;
2
3pipeline{
4
5    agent any
6    parameters {
7        string(name: 'BROWSER_TYPE', defaultValue: 'chrome', description: 'Type a browser type, should be chrome/firefox')
8        string(name: 'TEST_SERVER_URL', defaultValue: '', description: 'Type the test server url')
9        string(name: 'NODE', defaultValue: 'win-anthony-demo', description: 'Please choose a windows node to execute this job.')
10    }
11    
12  stages{
13      stage("Initialization"){
14          steps{
15              script{
16                  browser_type = BROWSER_TYPE?.trim()
17                  test_url = TEST_SERVER_URL?.trim()
18                  win_node = NODE?.trim()
19              }
20          }
21      }
22
23      stage("Git Checkout"){
24          steps{
25              script{
26                  node(win_node) {
27                       checkout([$class: 'GitSCM', branches: [[name: '*/master']],
28                          userRemoteConfigs: [[credentialsId: '6f4fa66c-eb02-46dc-a4b3-3a232be5ef6e',
29                          url: 'https://github.com/QAAutomationLearn/JavaAutomationFramework.git']]])
30                  }
31              }
32          }
33      }
34     
35        stage("Set key value"){
36          steps{
37              script{
38                  node(win_node){
39                      selenium_test = load env.WORKSPACE + "\\pipeline\\selenium.groovy"
40                      config_file = env.WORKSPACE + "\\Configs\\config.properties"
41                      try{
42                          selenium_test.setKeyValue2("browser", browser_type, config_file)
43                          //test_url 你自己替代
44                          file_content = readFile config_file
45                            println file_content
46                      }catch (Exception e) {
47                          error("Error met:" + e)
48                      }
49                  }
50              }
51          }
52      }
53     
54      stage("Run Selenium Test"){
55          steps{
56              script{
57                  node(win_node){
58                      run_bat = env.WORKSPACE + "\\run.bat"
59                      bat (run_bat)
60                  }
61              }
62          }
63      }
64  }
65
66
67
68}
69
70

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1import hudson.model.*;
2import java.io.FileInputStream;
3import java.io.FileNotFoundException;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.util.Properties;
7
8def setKeyValue(key, value, file_path) {
9    // read file, get string object
10    file_content_old = readFile file_path
11    println file_content_old
12    //遍历每一行,判断,然后替换字符串
13    lines = file_content_old.tokenize("\n")
14    new_lines = []
15    lines.each { line ->
16        if(line.trim().startsWith(key)) {
17            line = key + "=" + value
18            new_lines.add(line)
19        }else {
20            new_lines.add(line)
21        }
22    }
23    // write into file
24    file_content_new = ""
25    new_lines.each{line ->
26        file_content_new += line + "\n"
27    }
28
29    writeFile file: file_path, text: file_content_new, encoding: "UTF-8"
30}
31return this;
32

测试结果:

http://65.49.216.200:8080/job/selenium-pipeline-demo/23/console

主要日志如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
1[Pipeline] node
2Running on win-anthony-demo in C:\JenkinsNode\workspace\selenium-pipeline-demo
3[Pipeline] {
4[Pipeline] load
5[Pipeline] { (C:\JenkinsNode\workspace\selenium-pipeline-demo\pipeline\selenium.groovy)
6[Pipeline] }
7[Pipeline] // load
8[Pipeline] readFile
9[Pipeline] echo
10baseURL=http://demo.guru99.com/v4/index.php
11# https://www.utest.com  backup website
12userName=mngr169501
13password=sYhYtUd
14
15# browser driver path
16firefoxpath=./Drivers\\geckodriver.exe
17chromepath=./Drivers\\chromedriver.exe
18
19# browser instance
20# the browser vlaue will only be firefox or chrome here
21browser=chrome
22
23
24[Pipeline] writeFile
25[Pipeline] readFile
26[Pipeline] echo
27baseURL=http://demo.guru99.com/v4/index.php
28# https://www.utest.com  backup website
29userName=mngr169501
30password=sYhYtUd
31
32# browser driver path
33firefoxpath=./Drivers\\geckodriver.exe
34chromepath=./Drivers\\chromedriver.exe
35
36# browser instance
37# the browser vlaue will only be firefox or chrome here
38browser=chrome
39
40
41[Pipeline] }
42[Pipeline] // node
43[Pipeline] }
44[Pipeline] // script
45[Pipeline] }
46[Pipeline] // stage
47[Pipeline] stage
48[Pipeline] { (Run Selenium Test)
49[Pipeline] script
50[Pipeline] {
51[Pipeline] node
52Running on win-anthony-demo in C:\JenkinsNode\workspace\selenium-pipeline-demo
53[Pipeline] {
54[Pipeline] bat
55[selenium-pipeline-demo] Running batch script
56C:\JenkinsNode\workspace\selenium-pipeline-demo>C:\JenkinsNode\workspace\selenium-pipeline-demo\run.bat
57
58C:\JenkinsNode\workspace\selenium-pipeline-demo>cd C:\Users\Anthont\git\AnthonyWebAutoDemo
59
60C:\Users\Anthont\git\AnthonyWebAutoDemo>mvn clean install
61[INFO] Scanning for projects...
62[WARNING]
63[WARNING] Some problems were encountered while building the effective model for AnthonyAutoV10:AnthonyAutoV10:jar:0.0.1-SNAPSHOT
64[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 19, column 15
65[WARNING]
66[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
67[WARNING]
68[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
69[WARNING]
70[INFO]
71[INFO] -------------------< AnthonyAutoV10:AnthonyAutoV10 >--------------------
72[INFO] Building AnthonyAutoV10 0.0.1-SNAPSHOT
73[INFO] --------------------------------[ jar ]---------------------------------
74[WARNING] The POM for com.beust:jcommander:jar:1.66 is missing, no dependency information available
75[INFO]
76[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ AnthonyAutoV10 ---
77[INFO] Deleting C:\Users\Anthont\git\AnthonyWebAutoDemo\target
78[INFO]
79[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ AnthonyAutoV10 ---
80[INFO] Using 'UTF-8' encoding to copy filtered resources.
81[INFO] skip non existing resourceDirectory C:\Users\Anthont\git\AnthonyWebAutoDemo\src\main\resources
82[INFO]
83[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ AnthonyAutoV10 ---
84[INFO] Nothing to compile - all classes are up to date
85[INFO]
86[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ AnthonyAutoV10 ---
87[INFO] Using 'UTF-8' encoding to copy filtered resources.
88[INFO] skip non existing resourceDirectory C:\Users\Anthont\git\AnthonyWebAutoDemo\src\test\resources
89[INFO]
90[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ AnthonyAutoV10 ---
91[INFO] Changes detected - recompiling the module!
92[INFO] Compiling 11 source files to C:\Users\Anthont\git\AnthonyWebAutoDemo\target\test-classes
93[INFO]
94[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ AnthonyAutoV10 ---
95[INFO] Surefire report directory: C:\Users\Anthont\git\AnthonyWebAutoDemo\target\surefire-reports
96
97-------------------------------------------------------
98 T E S T S
99-------------------------------------------------------
100Running TestSuite
101Starting ChromeDriver 2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab) on port 1780
102Only local connections are allowed.
103Dec 23, 2018 9:52:43 PM org.openqa.selenium.remote.ProtocolHandshake createSession
104INFO: Detected dialect: OSS
105 INFO [main] (TC_NewCustomer_004.java:22)- Login is completed
106 INFO [main] (TC_NewCustomer_004.java:28)- Proving customer details.............
107 INFO [main] (TC_NewCustomer_004.java:46)- Validating adding new customer..............
108Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 166.426 sec - in TestSuite
109
110Results :
111
112Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
113
114[INFO]
115[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ AnthonyAutoV10 ---
116[WARNING] JAR will be empty - no content was marked for inclusion!
117[INFO] Building jar: C:\Users\Anthont\git\AnthonyWebAutoDemo\target\AnthonyAutoV10-0.0.1-SNAPSHOT.jar
118[INFO]
119[INFO] --- maven-install-plugin:2.4:install (default-install) @ AnthonyAutoV10 ---
120[INFO] Installing C:\Users\Anthont\git\AnthonyWebAutoDemo\target\AnthonyAutoV10-0.0.1-SNAPSHOT.jar to C:\Users\Anthont\.m2\repository\AnthonyAutoV10\AnthonyAutoV10\0.0.1-SNAPSHOT\AnthonyAutoV10-0.0.1-SNAPSHOT.jar
121[INFO] Installing C:\Users\Anthont\git\AnthonyWebAutoDemo\pom.xml to C:\Users\Anthont\.m2\repository\AnthonyAutoV10\AnthonyAutoV10\0.0.1-SNAPSHOT\AnthonyAutoV10-0.0.1-SNAPSHOT.pom
122[INFO] ------------------------------------------------------------------------
123[INFO] BUILD SUCCESS
124[INFO] ------------------------------------------------------------------------
125[INFO] Total time:  03:05 min
126[INFO] Finished at: 2018-12-23T21:55:24+08:00
127[INFO] ------------------------------------------------------------------------
128[Pipeline] }
129[Pipeline] // node
130[Pipeline] }
131[Pipeline] // script
132[Pipeline] }
133[Pipeline] // stage
134[Pipeline] }
135[Pipeline] // withEnv
136[Pipeline] }
137[Pipeline] // node
138[Pipeline] End of Pipeline
139Finished: SUCCESS
140

这里灵活的参数,我们实现了需求。

Jenkins高级篇之Pipeline实践篇-6-Selenium和Jenkins持续集成-pipeline参数化构建selenium自动化测试

下一篇文章,我们来思考下如何把测试过程的日志和报告文件给放到Jenkins上,点击链接可以预览。这个我之前也没有做过,先研究下,有知道的同学可以告诉我哈。

 

给TA打赏
共{{data.count}}人
人已打赏
安全经验

职场中的那些话那些事

2021-9-24 20:41:29

安全经验

elk+redis 搭建nginx日志分析平台

2021-11-28 16:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索