donal
2018-04-27 ec5c7dd52f18d9993e8ca55955ce7d3f0460d085
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
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
8 - Performance Testing
9 - Security testing
10 - Static Code analysis
11 - Vulnerability scanning
12
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.
14
15 For example; imagine a developer called `Sam` has checked in some poor performing function into an API that spikes it's 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.
16
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 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.
18
19 Static code analyis 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 to execute in a build.
20
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
ec5c7d 40 > Below is a collection of the new frameworks and tools that will be used in this lab
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.
ec5c7d 43
D 44 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 45
D 46 ## Big Picture
47 This exercise begins cluster containing blah blah
48
49 _____
50
51 ## 10,000 Ft View
064b38 52 > 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 53
007b55 54 2. Add a parallel stage after the e2e tests on the front end to run OWASP Zap and Arachni against the deployed apps.
43f2f2 55
007b55 56 2. Add Code Coverage reporing to the build for gaining greater insight into test improvements.
D 57
ec5c7d 58 2. Add `npm run lint` to the Frontend and report the result using the Checkstyle Plugin in Jenkins.
007b55 59
D 60 2. Create a new Jenkins job to run some light performance testing against the API layer using the perf tests tasks.
43f2f2 61
D 62 ## Step by Step Instructions
007b55 63 > This is a well structured guide with references to exact filenames and indications as to what should be done.
43f2f2 64
007b55 65 ### Part 1 - Add Security scanning to the pipeline 
dc377a 66 > _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 67
dc377a 68 2. Open the `todolist-fe` application's `Jenkinsfile` in your favourite editor. The file is stored in the root of the project.
D 69
70 2. The file is layed 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 71 ![stages](../images/exercise5/stages.png)
dc377a 72
064b38 73 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 74 ```groovy
D 75         stage("e2e test") {
76             // ... stuff in here ....
77         }
78         stage("security scanning") {
79             parallel {
80                 stage('OWASP Scan') {
81
82                 }
83                 stage('Arachni Scan') {
84
85                 }
86             }
87         }
43f2f2 88 ```
dc377a 89
064b38 90 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 91 ```groovy
D 92 stage('OWASP Scan') {
93     agent {
94         node {
95             label "jenkins-slave-zap"
96         }
97     }
98     when {
99         expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
100     }
101 }
43f2f2 102 ```
dc377a 103
3dce53 104 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 105 ```groovy
D 106 stage('OWASP Scan') {
3dce53 107         agent {
D 108             node {
109                 label "jenkins-slave-zap"
110             }
dc377a 111         }
3dce53 112         when {
D 113             expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
114         }
115         steps {
116             sh '''
117                 /zap/zap-baseline.py -r index.html -t ${E2E_TEST_ROUTE} || return_code=$?
118                 echo "exit value was  - " $return_code
119             '''
120         }
dc377a 121 }
D 122 ```
123
124 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 a HTML report.
125 ```groovy
126 stage('OWASP Scan') {
127     agent {
128         node {
129             label "jenkins-slave-zap"
130         }
131     }
132     when {
133         expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
134     }
135     steps {
136         sh '''
3dce53 137             /zap/zap-baseline.py -r index.html -t http://${E2E_TEST_ROUTE} || return_code=$?
D 138             echo "exit value was  - " $return_code
dc377a 139         '''
D 140     }
141     post {
142         always {
143           // publish html
144           publishHTML target: [
145               allowMissing: false,
146               alwaysLinkToLastBuild: false,
147               keepAll: true,
148               reportDir: '/zap/wrk',
149               reportFiles: 'index.html',
150               reportName: 'Zap Branniscan'
151             ]
152         }
153     }
154 }
155 ```
156
064b38 157 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 158 ```groovy
D 159     stage('Arachni Scan') {
160         agent {
161             node {
162                 label "jenkins-slave-arachni"
163             }
164         }
165         when {
166             expression { GIT_BRANCH ==~ /(.*master|.*develop)/ }
167         }
168         steps {
169             sh '''
da9923 170                 /arachni/bin/arachni http://${E2E_TEST_ROUTE} --report-save-path=arachni-report.afr
dc377a 171                 /arachni/bin/arachni_reporter arachni-report.afr --reporter=xunit:outfile=report.xml --reporter=html:outfile=web-report.zip
D 172                 unzip web-report.zip -d arachni-web-report
173             '''
174         }
175         post {
176             always {
177                 junit 'report.xml'
178                 publishHTML target: [
179                     allowMissing: false,
180                     alwaysLinkToLastBuild: false,
181                     keepAll: true,
182                     reportDir: 'arachni-web-report',
183                     reportFiles: 'index.html',
184                     reportName: 'Arachni Web Crawl'
185                     ]
186             }
187         }
188     }
189 ```
190
7c2c91 191 2. With this config in place run a build on Jenkins. To do this; commit your code (from your terminal):
D 192 ```bash
193 $ git add .
194 $ git commit -m "ADD - security scanning tools to pipeline"
195 $ git push
196 ```
197
3dce53 198 2. Check out the Blue Ocean Jenkins view for how the parallel stage is viewed!
D 199 ![jenkins-parallel](../images/exercise5/jenkins-parallel.png)
200
7c2c91 201 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 202 ![report-arachni](../images/exercise5/report-arachni.png)
D 203 ![jenkins-arachni](../images/exercise5/jenkins-arachni.png)
204
205 <p class="tip">
3dce53 206 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 207 </p>
43f2f2 208
2c15b7 209 2. TODO - add solution for failing Security scans!
D 210
007b55 211 ### Part 2 - Add Code Coverage & Linting to the pipeline
dabc6f 212 > _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 213
dabc6f 214 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 215
3dce53 216 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 repor the coverage stats.
dabc6f 217 ```groovy
D 218     // Post can be used both on individual stages and for the entire build.
219     post {
220         always {
221             archive "**"
222             junit 'test-report.xml'
223             // publish html
224             publishHTML target: [
225                 allowMissing: false,
226                 alwaysLinkToLastBuild: false,
227                 keepAll: true,
228                 reportDir: 'reports/coverage',
229                 reportFiles: 'index.html',
230                 reportName: 'Code Coverage'
231             ]
232         }
233 ```
234
4332f4 235 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 236 ```groovy
D 237 echo '### Install deps ###'
238 sh 'npm install'
239 echo '### Running linting ###'
3dce53 240 sh 'npm run lint'
dabc6f 241 ```
D 242
243 3. Save the `Jenkinsfile` and commit it to trigger a build with some more enhancements.
244 ```bash
245 $ git add .
246 $ git commit -m "ADD - linting and coverage to the pipeline"
247 $ git push
248 ```
249
3dce53 250 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 251 ![linting-issue](../images/exercise5/linting-issue.png)
252
253 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 254 <p class="tip">
A 255 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.
256 </p>
3dce53 257 ![report-location](../images/exercise5/report-location.png)
D 258
259 3. Open the report to drill down into detail of where testing coverage could be improved! 
5277ca 260 ![report-coverage](../images/exercise5/report-coverage.png)
D 261 <p class="tip">
262 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. 
263 </p>
264
dabc6f 265 3. (Optional Step) - Install the Checkstyle plugin; and add `checkstyle pattern: 'eslint-report.xml'` below the `publishHTML` block to add reporting to Jenkins!
D 266
5277ca 267 ### Part 3 - Nightly light performance testing
D 268 > _In this exercise, we will execute the light performance tasks in our API to collect data about throughtput time in hopes if the API ever has some `Sam` quality code checked in, we will spot it_
dabc6f 269
2c15b7 270 An arbitrary value for the API's 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 271
2c15b7 272 4. Create a new Item on Jenkins, `nightly-perf-test` and make it a freestyle job.
D 273 ![new-job](../images/exercise5/new-job.png)
274
275 4. Set the `label` on `Restrict where this project can be run` to `jenkins-slave-npm` one used by the build jobs previously.
276 ![slave-label](../images/exercise5/slave-label.png)
5277ca 277
D 278 4. In the SCM section; set the project to use the `todolist-api` git project. Set the credentials accordingly.
2c15b7 279 ![git-settings](../images/exercise5/git-settings.png)
D 280
281 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 * * *`.
282 ![build-schedule](../images/exercise5/build-schedule.png)
283
284 4. Set the `Color ANSI Console Output` on the Build Environment section.
5277ca 285
4332f4 286 4. Click `add build step` and select `execute shell` and add the following to it, replacing `<YOUR_NAME>` and `somedomain` 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 287 ```bash
D 288 export E2E_TEST_ROUTE=todolist-api-<YOUR_NAME>-dev.apps.somedomain.com
289 npm install
290 set +e
291 npm run perf-test:create
292 rc1=$?
293 npm run perf-test:show
294 rc2=$?
295 set ­-e
296 exit $(($rc1 | $rc2))
297 ```
298
299 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`.
300
21cad6 301 4. On the new dialog, name the Plot group eg `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 fiel` checkbox. Apply those changes
5277ca 302 ![jenkins-plot](../images/exercise5/jenkins-plot.png)
D 303
4332f4 304 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 305
D 306 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
307 ![result-plot](../images/exercise5/result-plot.png)
43f2f2 308
D 309 _____
310
311 ## Extension Tasks
312 > _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._
313
dabc6f 314  - Enhance the `todolist-api` with the security scanning tools as you've done for the `todolist-api`
D 315  - Enhance the `todolist-api` with the coverage reporting as you've done for `todolist-api`
007b55 316  - Add Black Duck or other package scanning tooling for our NodeJS app
D 317  - Add Container Vulnerability scanning tooling to the pipeline
5277ca 318  - Add `Stryker` to create mutants and do additional non functional testing of the App
dabc6f 319  - Add the Checkstyle plugin to Jenkins for reporting scores
43f2f2 320
D 321 ## Additional Reading
322 > List of links or other reading that might be of use / reference for the exercise
323
01c4da 324 ## Slide Links
RH 325
326 - [Intro](https://docs.google.com/presentation/d/1YQ0hUV3o7DW8O40SiI-BQZXCOSVeQGjo2iTxCL2GZfk/)
327 - [Wrap-up](https://docs.google.com/presentation/d/102hRHDlC9PUIsMs3m1fZy8QUaB5UKzBlhBPdehRWw38/)
328 - [All Material](https://drive.google.com/drive/folders/1seT0V3ABHNonvtFvORNt836NgSeYPuWW)