Ravi Srinivasan
2019-01-24 14a9667e1209a90792a2b8bd612be3ae2b25077e
commit | author | age
064b38 1 # The Non-Functionals Strike back
5277ca 2 > In this exercise we explore the non-functional side of testing.
5afd94 3
D 4 ![death-star-vent](../images/exercise5/death-star-vent.jpeg)
ec5c7d 5
D 6 ## Exercise Intro
1173e5 7 Non-functional testing provides valuable insights into code quality and application performance. Often overlooked but usually one of the most essential types of testing, non-functional testing types can include, but are not limited to
ec5c7d 8 - Performance Testing
D 9 - Security testing
10 - Static Code analysis
11 - Vulnerability scanning
12
1173e5 13 There are many tools out there for supporting these testing types but often they are left to the end of a delivery. Many traditional projects will leave Performance testing or security sign off to a few weeks before Go Live. This raises the question of what do we do if things do not pass these tests? Do we hold off the Go Live or accept the risk? In most cases we can learn earlier if things will be show stoppers and more importantly we can automate them.
ec5c7d 14
e43fd2 15 For example; imagine a developer called `Sam` has checked in some poorly performing function into an API that spikes its response time. Let's call this `Sam Code`. This `Sam Code` may not be caught by our Unit Tests but could have very big impact on application usability. Before building code on top this and it becoming more of an issue at the end of a project; we could code and capture metrics around API response time and track these over time and hopefully spot regressions earlier.
ec5c7d 16
2576ab 17 Another one of the age old questions is "How do we know we're testing enough?". Well the simple answer is you can never do enough testing! But how do we know we are testing the right things? Code coverage metrics can be run on our application while running the tests. They can identify what files are being tested and a line by line of how many times a test executes against a block of code. Reporting these metrics in our pipeline gives a greater handle on the quality of our testing.
ec5c7d 18
2576ab 19 Static code analysis can provide great insights into the quality of the code we've written. By analysing code without executing it bugs and common gotchas can be identified. Code complexity can be assessed using tooling such as SonarQube. Linting of code is a useful thing for non compiled languages such as JavaScript and can be executed in a build to provide some feedback.
ec5c7d 20
D 21 Integrating these tools into the developer workflow can greatly improve quality and readability of code. Putting them in the pipeline ensures they are executed - removing the _"It works on my machine"_ view some may take.
22
23 #### Why run non functional tests?
24 - Early identify common code gotchas and pitfalls
25 - Tighten our feedback loop by executing non functional tests earlier in a project lifecycle
26 - Improve Code readability with agreeing a coding standard and then codifying it.
27 - Improve trust in the code quality and bring together security teams with dev teams earlier
28 - They can be automated; so why not run them as part of a build!
29
43f2f2 30 _____
D 31
32 ## Learning Outcomes
33 As a learner you will be able to
007b55 34 - Create additional Jenkins stages to scan for security vulnerabilities in the Apps
064b38 35 - Assess test quality by producing coverage reports as part of a build
007b55 36 - Improve code readability with linting
D 37 - Do some light performance testing to monitor throughput of APIs
43f2f2 38
D 39 ## Tools and Frameworks
b5d705 40 > Below is a collection of the new frameworks and tools that will be used in this exercise
43f2f2 41
007b55 42 1. [eslint](https://eslint.org/) - ESLint is an open source JavaScript linting utility originally created by Nicholas C. Zakas in June 2013. Code linting is a type of static analysis that is frequently used to find problematic patterns or code that doesn’t adhere to certain style guidelines. There are code linters for most programming languages, and compilers sometimes incorporate linting into the compilation process.
2576ab 43 1. [Zed Attack Proxy](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) - The OWASP Zed Attack Proxy (ZAP) is one of the world’s most popular free security tools and is actively maintained by hundreds of international volunteers*. It can help you automatically find security vulnerabilities in your web applications while you are developing and testing your applications. Its also a great tool for experienced pentesters to use for manual security testing.
D 44 1. [Arachni Crawler](http://www.arachni-scanner.com/) - Arachni is a feature-full, modular, high-performance Ruby framework aimed towards helping penetration testers and administrators evaluate the security of modern web applications. It is free, with its source code public and available for review. It is versatile enough to cover a great deal of use cases, ranging from a simple command line scanner utility, to a global high performance grid of scanners, to a Ruby library allowing for scripted audits, to a multi-user multi-scan web collaboration platform. In addition, its simple REST API makes integration a cinch.
ec5c7d 45 1. [stryker](http://stryker-mutator.io/) - Mutation testing! What is it? Bugs, or mutants, are automatically inserted into your production code. Your tests are run for each mutant. If your tests fail then the mutant is killed. If your tests passed, the mutant survived. The higher the percentage of mutants killed, the more effective your tests are. It's really that simple.
43f2f2 46
D 47 ## Big Picture
664135 48 > From the previous exercise; we introduced pipeline-as-code and new Jenkins Slave nodes. This exercise focuses on extending the pipeline with Non-functional testin and some automated security testing.
D 49
14a966 50 ![big-picture](../images/big-picture/big-picture-5.jpg)
43f2f2 51
D 52 _____
53
54 ## 10,000 Ft View
064b38 55 > This lesson will use the Exercise 4's Zap Slave and Arachni scanner to improve the pipeline. Linting will be included in the build and code coverage too.
43f2f2 56
007b55 57 2. Add a parallel stage after the e2e tests on the front end to run OWASP Zap and Arachni against the deployed apps.
43f2f2 58
2576ab 59 2. Add Code Coverage reporting to the build for gaining greater insight into test improvements.
007b55 60
ec5c7d 61 2. Add `npm run lint` to the Frontend and report the result using the Checkstyle Plugin in Jenkins.
007b55 62
D 63 2. Create a new Jenkins job to run some light performance testing against the API layer using the perf tests tasks.
43f2f2 64
D 65 ## Step by Step Instructions
007b55 66 > This is a well structured guide with references to exact filenames and indications as to what should be done.
43f2f2 67
1173e5 68 ### Part 1 - Add Security scanning to the pipeline
dc377a 69 > _In this exercise the first of our non-functional testing is explored in the form of some security scanning. We will add the scans to our Jenkinsfile and have them run as new stages_
43f2f2 70
dc377a 71 2. Open the `todolist-fe` application's `Jenkinsfile` in your favourite editor. The file is stored in the root of the project.
D 72
e43fd2 73 2. The file is laid out with a collection of stages that correspond to each part of our build as seen below. We will create a new stage to execute in parallel.
cd34aa 74 ![stages](../images/exercise5/stages.png)
dc377a 75
1173e5 76 2. Create a new Parallel Stage called `security scanning` underneath the `stage("e2e test") { }` section as shown below. The contents of the `e2e test` have been removed for simplicity.
dc377a 77 ```groovy
D 78         stage("e2e test") {
79             // ... stuff in here ....
80         }
81         stage("security scanning") {
82             parallel {
83                 stage('OWASP Scan') {
84
85                 }
86                 stage('Arachni Scan') {
87
88                 }
89             }
90         }
43f2f2 91 ```
dc377a 92
064b38 93 2. Let's start filling out the configuration for the OWASP Zap scan first. We will set the label to our slave created in previous exercise and a `when` condition of the master or develop branch.
dc377a 94 ```groovy
D 95 stage('OWASP Scan') {
96     agent {
97         node {
98             label "jenkins-slave-zap"
99         }
100     }
101     when {
102         expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
103     }
104 }
43f2f2 105 ```
dc377a 106
3dce53 107 2.  Add a `step` with a `sh` command to run the tool by passing in the URL of the app we're going to test.
dc377a 108 ```groovy
D 109 stage('OWASP Scan') {
3dce53 110         agent {
D 111             node {
112                 label "jenkins-slave-zap"
113             }
dc377a 114         }
3dce53 115         when {
D 116             expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
117         }
118         steps {
119             sh '''
120                 /zap/zap-baseline.py -r index.html -t ${E2E_TEST_ROUTE} || return_code=$?
121                 echo "exit value was  - " $return_code
122             '''
123         }
dc377a 124 }
D 125 ```
126
e43fd2 127 2.  Finally add the reporting for Jenkins in `post` hook of our Declarative Pipeline. This is to report the findings of the scan in Jenkins as an HTML report.
dc377a 128 ```groovy
D 129 stage('OWASP Scan') {
130     agent {
131         node {
132             label "jenkins-slave-zap"
133         }
134     }
135     when {
136         expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
137     }
138     steps {
139         sh '''
3dce53 140             /zap/zap-baseline.py -r index.html -t http://${E2E_TEST_ROUTE} || return_code=$?
D 141             echo "exit value was  - " $return_code
dc377a 142         '''
D 143     }
144     post {
145         always {
146           // publish html
147           publishHTML target: [
148               allowMissing: false,
149               alwaysLinkToLastBuild: false,
150               keepAll: true,
151               reportDir: '/zap/wrk',
152               reportFiles: 'index.html',
153               reportName: 'Zap Branniscan'
154             ]
155         }
156     }
157 }
158 ```
159
064b38 160 2. Let's add our Arachni Scan to the second part of the parallel block. The main difference between these sections is Jenkins will report an XML report too for failing the build accordingly. Below is the snippet for the Arachni scanning.
dc377a 161 ```groovy
D 162     stage('Arachni Scan') {
163         agent {
164             node {
165                 label "jenkins-slave-arachni"
166             }
167         }
168         when {
169             expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
170         }
171         steps {
172             sh '''
da9923 173                 /arachni/bin/arachni http://${E2E_TEST_ROUTE} --report-save-path=arachni-report.afr
dc377a 174                 /arachni/bin/arachni_reporter arachni-report.afr --reporter=xunit:outfile=report.xml --reporter=html:outfile=web-report.zip
D 175                 unzip web-report.zip -d arachni-web-report
176             '''
177         }
178         post {
179             always {
180                 junit 'report.xml'
181                 publishHTML target: [
182                     allowMissing: false,
183                     alwaysLinkToLastBuild: false,
184                     keepAll: true,
185                     reportDir: 'arachni-web-report',
186                     reportFiles: 'index.html',
187                     reportName: 'Arachni Web Crawl'
188                     ]
189             }
190         }
191     }
192 ```
193
7c2c91 194 2. With this config in place run a build on Jenkins. To do this; commit your code (from your terminal):
D 195 ```bash
fad576 196 git add .
D 197 ```
198 ```bash
199 git commit -m "ADD - security scanning tools to pipeline"
200 ```
201 ```bash
202 git push
7c2c91 203 ```
D 204
3dce53 205 2. Check out the Blue Ocean Jenkins view for how the parallel stage is viewed!
D 206 ![jenkins-parallel](../images/exercise5/jenkins-parallel.png)
207
7c2c91 208 2. Once the Jobs have completed; navigate to the Jobs status and see the scores. You can find the graphs and test reports on overview of the Job. Explore the results!
cd34aa 209 ![report-arachni](../images/exercise5/report-arachni.png)
D 210 ![jenkins-arachni](../images/exercise5/jenkins-arachni.png)
211
212 <p class="tip">
3dce53 213 NOTE - your build may have failed because of the a security failure but the reports should still be generated, it is OK to proceed with the next exercise!
cd34aa 214 </p>
43f2f2 215
2c15b7 216 2. TODO - add solution for failing Security scans!
D 217
007b55 218 ### Part 2 - Add Code Coverage & Linting to the pipeline
dabc6f 219 > _Let's continue to enhance our pipeline with some non-functional testing. Static code analysis and testing coverage reports can provide a useful indicator on code quality and testing distribution_
43f2f2 220
dabc6f 221 3. Coverage reports are already being generated as part of the tests. We can have Jenkins produce a HTML report showing in detail where our testing is lacking. Open the `todolist-fe` in your favourite editor.
D 222
1173e5 223 3. Open the `Jenkinsfile` in the root of the project; move to the `stage("node-build"){ ... }` section. In the `post` section add a block for producing a `HTML` report as part of our builds. This is all that is needed for Jenkins to report the coverage stats.
dabc6f 224 ```groovy
D 225     // Post can be used both on individual stages and for the entire build.
226     post {
227         always {
228             archive "**"
229             junit 'test-report.xml'
230             // publish html
231             publishHTML target: [
232                 allowMissing: false,
233                 alwaysLinkToLastBuild: false,
234                 keepAll: true,
235                 reportDir: 'reports/coverage',
236                 reportFiles: 'index.html',
237                 reportName: 'Code Coverage'
238             ]
239         }
240 ```
241
1173e5 242 3. To get the linting working; we will add a new step to our `stage("node-build"){ }` section to lint the JavaScript code. Continuing in the `Jenkinsfile`, After the `npm install`; add a command to run the linting.
dabc6f 243 ```groovy
D 244 echo '### Install deps ###'
245 sh 'npm install'
246 echo '### Running linting ###'
3dce53 247 sh 'npm run lint'
dabc6f 248 ```
D 249
250 3. Save the `Jenkinsfile` and commit it to trigger a build with some more enhancements.
251 ```bash
fad576 252 git add .
D 253 ```
254 ```bash
255 git commit -m "ADD - linting and coverage to the pipeline"
256 ```
257 ```bash
258 git push
dabc6f 259 ```
D 260
3dce53 261 3. When the build has completed; fix the linting errors if there are any and commit your changes. Look in Jenkins log for what the issue might be....
D 262 ![linting-issue](../images/exercise5/linting-issue.png)
263
1173e5 264 3. To view the coverage graph; go to the job's build page and open the `Code Coverage` report from the nav bar on the side.
4332f4 265 <p class="tip">
A 266 NOTE - Sometimes this won't display on the `yourjenkins.com/job/todolist-fe/job/branch/` sidebar, click on an individual build in the build history and it should appear on the side navbar.
267 </p>
3dce53 268 ![report-location](../images/exercise5/report-location.png)
D 269
1173e5 270 3. Open the report to drill down into detail of where testing coverage could be improved!
5277ca 271 ![report-coverage](../images/exercise5/report-coverage.png)
D 272 <p class="tip">
1173e5 273 NOTE - a good practice for teams is to try and increase the code coverage metrics over the life of a project. Teams will often start low and use practices such as retrospective to increase the quality at specific times.
5277ca 274 </p>
D 275
dabc6f 276 3. (Optional Step) - Install the Checkstyle plugin; and add `checkstyle pattern: 'eslint-report.xml'` below the `publishHTML` block to add reporting to Jenkins!
D 277
5277ca 278 ### Part 3 - Nightly light performance testing
1173e5 279 > _In this exercise, we will execute the light performance tasks in our API to collect data about throughput time in hopes if the API ever has some `Sam` quality code checked in, we will spot it_
dabc6f 280
1173e5 281 An arbitrary value for the APIs to respond in has been chosen. It is set in the `todolist-api/tasks/perf-test.js` file. In this exercise we will get Jenkins to execute the tests and fail based on the score set there!
5277ca 282
2c15b7 283 4. Create a new Item on Jenkins, `nightly-perf-test` and make it a freestyle job.
D 284 ![new-job](../images/exercise5/new-job.png)
285
286 4. Set the `label` on `Restrict where this project can be run` to `jenkins-slave-npm` one used by the build jobs previously.
287 ![slave-label](../images/exercise5/slave-label.png)
5277ca 288
D 289 4. In the SCM section; set the project to use the `todolist-api` git project. Set the credentials accordingly.
2c15b7 290 ![git-settings](../images/exercise5/git-settings.png)
D 291
292 4. Set the build to execute each night; for example 0300 in the morning. Hit `Build periodically` on the Build Triggers section and set it to `H 3 * * *`.
293 ![build-schedule](../images/exercise5/build-schedule.png)
294
295 4. Set the `Color ANSI Console Output` on the Build Environment section.
5277ca 296
33c738 297 4. Click `add build step` and select `execute shell` and add the following to it, replacing `<YOUR_NAME>` as expected. We will just test the `create` and `show` API for the moment. We are grabbing the response code of the perf-test to keep Jenkins running both shells steps and then exiting with whichever fails:
5277ca 298 ```bash
530a25 299 export E2E_TEST_ROUTE=todolist-api-<YOUR_NAME>-dev.<APPS_URL>
5277ca 300 npm install
D 301 set +e
302 npm run perf-test:create
303 rc1=$?
304 npm run perf-test:show
305 rc2=$?
306 set ­-e
307 exit $(($rc1 | $rc2))
308 ```
309
310 4. On the Post Build actions section we will plot the data from the perf tests in Jenkins. Add a `Post-build Action > Plot Build Data`.
311
1173e5 312 4. On the new dialog, name the Plot group e.g. `benchmark-tests` and add `create­-api` as the Plot title. Set the `Number of Builds to Include` to a large number like `100`. Set the Data Series file to be `reports/server/perf/create-perf-score.csv` and mark the `Load data from CSV field` checkbox. Apply those changes
5277ca 313 ![jenkins-plot](../images/exercise5/jenkins-plot.png)
D 314
4332f4 315 4. Hit `Add Plot` to add another. Set Plot group to `benchmark-tests` again but this time setting the Plot title to `show­-api`. Set the Data Series file to be `reports/server/perf/show-perf-score.csv` and mark the `Load data from CSV` radio button. Save those changes and run the job (Job could take a while to execute!).
5277ca 316
D 317 4. Run it a few times to start to generate the data points on the plot. The `bench-tests` plot is available on the job's homepage
318 ![result-plot](../images/exercise5/result-plot.png)
43f2f2 319
D 320 _____
321
322 ## Extension Tasks
323 > _Ideas for go-getters. Advanced topic for doers to get on with if they finish early. These will usually not have a solution and are provided for additional scope._
324
dabc6f 325  - Enhance the `todolist-api` with the security scanning tools as you've done for the `todolist-api`
D 326  - Enhance the `todolist-api` with the coverage reporting as you've done for `todolist-api`
007b55 327  - Add Black Duck or other package scanning tooling for our NodeJS app
D 328  - Add Container Vulnerability scanning tooling to the pipeline
5277ca 329  - Add `Stryker` to create mutants and do additional non functional testing of the App
dabc6f 330  - Add the Checkstyle plugin to Jenkins for reporting scores
43f2f2 331
D 332 ## Additional Reading
333 > List of links or other reading that might be of use / reference for the exercise
334
01c4da 335 ## Slide Links
RH 336
337 - [Intro](https://docs.google.com/presentation/d/1YQ0hUV3o7DW8O40SiI-BQZXCOSVeQGjo2iTxCL2GZfk/)
338 - [Wrap-up](https://docs.google.com/presentation/d/102hRHDlC9PUIsMs3m1fZy8QUaB5UKzBlhBPdehRWw38/)
1173e5 339 - [All Material](https://drive.google.com/drive/folders/1seT0V3ABHNonvtFvORNt836NgSeYPuWW)