# 04.2-Security and DevOps Lesson2:Testing
###### tags: `Udacity`
# 01 Introduction to Testing
**Introduction to Testing**
Software testing is an important part of the software development process. Without it, you can't be sure that what you write works until it's already seeing real users. The objective of this lesson is to demonstrate the fundamentals of unit testing using ”JUnit” and ”Mockito” frameworks. In the first few concepts, we’ll introduce you to the software testing, in general. In the rest of the concepts, we'll look at unit-testing in depth and show you how to effectively write unit-test cases.
{%youtube jfRlA1ZxWUM%}
**Lesson Outline**
Here are the main topics we'll explore in this lesson:
- Basics of software testing
- What is unit testing?
- Introduction to JUnits framework
- How to write JUnit test using annotations
- What are mocks
- How to write tests using Mockito framework
- Adding tests for the authentication component previously developed in the eCommerce Application
# 02 What is Testing and Why Does it Matter?
**What is Testing?**
Testing means verification of the functionality of your application and make sure that all the parts work together exactly as they should. It essentially ensures that the application is bug-free and behaves correctly in as many scenarios as possible. Without it, bugs would be everywhere. The video goes over a few high profile cases where testing would have prevented massive, costly failures. Hopefully, after watching it you will gain an appreciation of the importance of good testing procedures.
{%youtube 7MB4QHK4Ssk%}
**Why Does Testing Matter?**
{%youtube kI8IGFCaz-U%}
# 03 Software Development Life CycleWhat is Software Development Life Cycle (SDLC)?
**What is Software Development Life Cycle (SDLC)?**
{%youtube 7v6u8Rh_ugQ%}
The **Software Development Life Cycle** (or **SDLC**) is a series of processes used to develop projects. Each phase of SDLC produces deliverables required by the next phase of the project cycle. Testing is one such deliverable that should be performed on a developed product based on the product requirements.
There are different SDLC models, such as Waterfall model, Iterative model, and Spiral model. These are the conventional models used for software development. These models differ in the number of iterations, the number of stages, and the deliverable of each stage.
**Few Famous SDLC Models**
Waterfall Model
This conventional SDLC model has the following six stages: requirement gathering, design, built, test, deploy, and maintain. Each stage must be completed before moving to the next stage. Hence, verification and validation are performed after each stage, along with elaborative documentation. This model is suitable for smaller projects because bugs (if any) can only be fixed within a stage. This model is not preferable where requirements change frequently. The testing stage comes a little late in this model. So it is expensive to make changes in the software built.
Agile Software Development
There is another sub-category of SDLC, called Agile Software Development. This category of models has an adaptive approach to developing software. Here, the requirements and corresponding solutions evolve collaboratively. It needs periodic interactions between all stakeholders, incremental development, better customer-collaborations, and easy to accommodate the requests for change. A few famous models under the Agile category are Extreme Programming (XP), Scrum, and Kanban. Agile models work on the customer-centric principles, as mentioned [here](https://agilemanifesto.org/principles.html).
Test-driven development (TDD)
Test-driven development (TDD), is an evolutionary approach to development which combines test-first development where you write a "test'' first. Later, you write the necessary development code to fulfill that test. It is the combination of test-first development and correspondingly refactoring the code. TDD makes it easier to conform to the requirements. Thediagram below presents the whole process of TDD:

**What are the Development, Test, and Production Environments?**
{%youtube ENcxQZgWTKY%}
# 04 Types of Software Testing
**Types of Software Testing**
In this concept, we would have a brief introduction to different types of software testing and dig deeper into Unit testing. Software testing is broadly divided into the following types - Functional, Non-Functional, and Maintenance testing, as described below:
* Functional testing is usually performed by the Quality and Development team and sometimes Business. Functional testing includes unit testing, integration testing, system testing, sanity testing, UAT(user acceptance testing) testing, regression, amongst - others.
* Non-Functional testing is performed by specialized testing teams. Non-functional testing includes performance testing, load testing, stress testing, security testing, reliability testing, usability testing, compliance testing, amongst others.
* Maintenance testing is performed on already deployed softwares. It includes regression testing, and confirmation testing. The need for maintenance testing arises when a software undergoes some addition/change in functionality.
{%youtube YlCVrRHDhDg%}
**Unit Testing**
Unit testing is the process of testing an individual, usually small, software module or component independently to find bugs. These tests are required to be written by the developers as it requires detailed knowledge of the code.
{%youtube CV2BCTewG28%}
# 05 Introduction to JUnits
**Introduction to JUnits**
We'll now go through a hands-on example that would get you some experience with JUnits. To follow along, you can download the starter code that the Instructor uses from [this](https://github.com/udacity/JDND/tree/master/exercises/c4%20-%20testing/starter%20code) GitHub repository.
1. Background
JUnit is a unit-testing "framework" to write repeatable tests in Java. To use this framework, you would need to perform the following steps:
* Download the `.jar` file from its official [website](https://junit.org/junit4/)
* Add the downloaded `.jar` file to your Test classpath in IDE
* Add the dependency to the `pom.xml` file in your IDE. `POM` is the abbreviation for "Project Object Model". The `pom.xml` file contains information about the project and configuration details used by Maven to build the project. A dependency can be added to the `pom.xml` file as follows:
```xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
```
Note that the version of JUnit may vary with time. We have done all the above steps for you in the project that you are going to download from our public repository on GitHub.
**Getting Started with JUnit**
As per convention, we would have the following two packages in our project:
* `src/main/java` - for Java classes
* `src/test/java` - for Unit Test classes For example, `Abacus.java` in `src/main/java` and AbacusTest.java in `src/test/java` package.
* Sample content of `Abacus.java` is given below:
```java
public class Abacus {
public int evaluate(String expression) {
int sum = 0;
for (String summand: expression.split("\\+"))
sum += Integer.valueOf(summand);
return sum;
}
}
```
* Sample content of `AbacusTest.java` in `src/test/java` package would look as follows:
```java
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class AbacusTest {
@Test
public void evaluatesExpression() {
Abacus abacus = new Abacus();
int sum = abacus.evaluate("10+20+30");
assertEquals(60, sum);
}
}
```
**Annotation**
JUnit uses annotation `@` before the definition of classes and methods that designate a test. Few frequently used annotations for methods are:
* `@Test` - Declares a method as a test method
* `@Before` - Runs before each test. It prepares the necessary state of the system (e.g., read input data, initialize the other classes)
* `@BeforeClass` - Runs once before any of the test methods in the class. In other words, it runs exactly once before the entire set of tests in the class..
* `@After` - Executed after each test. It releases the resources used for the test (e.g., delete temporary data, restore defaults) There are many more annotations that we may learn in the project code.
**Assert statement**
In the `AbacusTest.java` code snippet, there is a call to `assertEquals(60, sum)` method. It is an assertion. JUnit provides static methods in Assert class, to test certain conditions. These assertion methods start with the word assert. These methods allow us to specify the error message, the expected output, and the actual output. The assertion method checks the value returned by a test to the expected value. It throws an AssertionException if the comparison fails. Some useful assertion methods are:
* `assertTrue([message,] boolean condition)` - Checks that the boolean condition is true.
* `assertFalse([message,] boolean condition)` - Checks that the boolean condition is false.
* `assertEquals([message,] expected, actual)` - Tests that two values are the same.
* `assertEquals([message,] expected, actual, tolerance)` - Tests whether float or double values are identical. The tolerance is the number of decimals, which must be the same.
* `assertNull([message,] object)` - Checks that the object is null.
**Failed Tests**
It is essential to check our methods using the corresponding(相應) test methods. If a test fails, console output would tell what went wrong so that we may make the necessary correction. For example, if we change a statement in Abacus.java from sum += Integer.valueOf(summand); to sum -= Integer.valueOf(summand);, it would produce the following error:
```typescript
There was 1 failure:
1) evaluatesExpression(AbacusTest)
java.lang.AssertionError: expected:<60> but was:<-60>
at org.junit.Assert.fail(Assert.java:23)
```
2. Getting familiar with the starter code
{%youtube 6TdPhGKTUmM%}
3. Add the Maven Dependency
{%youtube gc58Hm-NK_M%}
4. Writing JUnits for the helper methods
{%youtube pzUEW_mJnL8%}
5. Access modifier and Return type of JUnits methods
{%youtube O6oUEGU1iBM%}
==重點test should be void and public==
6. Writing tests on the `Helper` class
{%youtube DJ0_RCkECwk%}
==重點==
* 超好用的工具 要學
* 注意事項
* 不能放'=' 或是 'return'
* Debug的行數一定要在目前的行數才可以使用evaluate
1. assertEquals 比照兩個List內容same會true
2. assertEquals 比照兩個array內容same會false因為位置不同
3. assertArrayEquals 比照兩個array內容,會true
**Solution**
Below is the solution code for all of the tests, including getMergedList. We encourage you to try out as many of these as you like, and compare your code with the examples. (As always, it's possible your code looks a bit different and still accomplishes the end goal!)
```java
package com.udacity.examples.Testing;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.List;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class HelperTest {
@Test
public void test() {
assertEquals("test", "test1");
}
@Test
public void test1() {
assertEquals("test", "test");
}
/**
* Need to be void and public
* @return
*
* @Test
private String test2() {
return "";
}
*/
@Test
public void validate_getCount() {
List<String> empNames = Arrays.asList("sareeta", "", "john","");
assertEquals(2, Helper.getCount(empNames));
}
@Test
public void validate_3lengthString() {
List<String> empNames = Arrays.asList("sareeta", "", "Jeff","sam");
assertEquals(2, Helper.getStringsOfLength3(empNames));
}
/*
* Part 2
* why not to use test in the name?
* Because annotations s
*/
@Test
public void verify_list_is_squared(){
List<Integer> yrsOfExperience = Arrays.asList(13,4,15,6,17,8,19,1,2,3);
List<Integer> expected = Arrays.asList(169, 16, 225, 36, 289, 64, 361, 1, 4, 9);
assertEquals(expected, Helper.getSquareList(yrsOfExperience));
}
/**
* assertFail vs asserTrue
*/
@Before
public void init() {
System.out.println("init executed");
}
@After
public void teardown() {
System.out.println("teardown executed");
}
@Test
public void verify_merged_list(){
List<String> empNames = Arrays.asList("sareeta", "", "john","");
assertEquals("sareeta, john", Helper.getMergedList(empNames));
}
@Test
public void verify_getMax(){
List<Integer> empLevel = Arrays.asList(3,3,3,5,7,2,2,5,7,5);
assertEquals(7, Helper.getStats(empLevel).getMax());
}
/**
* this should be public static
*/
@BeforeClass
public static void initClass() {
System.out.println("init Class executed");
}
@AfterClass
public static void teardownclass() {
System.out.println("teardown Class executed");
}
/**
*assertArrayEquals
*How should you debug this?
*/
@Test
public void verify_ArrayListTest(){
int[] yrsOfExperience = {13,4,15,6,17,8,19,1,2,3};
int[] expected = {13,4,15,6,17,8,19,1,2,3};
assertArrayEquals(expected, yrsOfExperience);
}
/**
* parameterized test next class
*/
}
```
# 06 Advanced Features of JUnit
Advanced Features of JUnit
{%youtube VLuhu3OESuo%}
As we just saw in the video, you can check out [this page](http://junit.sourceforge.net/javadoc/org/junit/Assert.html) for a comprehensive list of all of the methods that the JUnits `Assert` class contains.
**Using @Before, @BeforeClass, @After, @AfterClass and @Ignore**
{%youtube DNPs_Jz9Xtg%}
**Parameterized tests**
{%youtube WyJcPLMcOOU%}
**@RunWith and @SelectClasses annotations from JUnit5 suite**
{%youtube H6_SHLZjwPw%}
> ??我問號
# 07 Code Coverage
**Code Coverage**
Code coverage is a measure used to find the degree to which the source code of a program is executed when the tests for that program are run. In other words, if running the tests results in 80% of the program's code being executed, then we would say that we have achieved 80% code coverage.
{%youtube L6GMayyvBNU%}
# 08 Macks
Mocks
Sometimes it is impossible or undesirable to directly work with a particular object, such as if that object is unavailable or impractical to work with. But we may still want to test our code to see how it works with that object. In such cases, we can create a mock object (or mock) that simulates the real object in specific, controlled ways—and then test our code using this simulated object. In this section, we'll explore how to create such mocks using a framework called Mockito.
{%youtube 14Okwxla5l8%}
# 09 Mockito
Mockito
Let's look at how we can create mocks using [Mockito](https://site.mockito.org/), mocking framework for unit tests in Java.
In this next video, we'll walk through building some mocks for the eCommerce application. You likely cloned the repository for this earlier in the course, but if you need it, you can find it [here](https://github.com/udacity/JDND/tree/master/projects/P04-eCommerce%20Application/starter_code).
**Writing `TestUtils`**
{%youtube UPFUQOdm8zY%}
**Few important methods and annotations provided by Mockito are:**
- [`mock()`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mock-java.lang.Class-)/[`@Mock`](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mock.html) - To create mock object. Here, `mock()` is an overloaded static method which accepts `Class<T> classToMock` as an argument and correspondingly returns a mock instance.
- [`when()`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#when-T-)/[`given()`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/BDDMockito.html#given-T-) - To specify the behaviour of mock object. `when()` method takes a particular method X as argument and set the expected (mocked) return value as Y. Following are the few examples:
```java
when(mock.someMethod()).thenReturn(200);
//parameterized methods as argument
when(mock.someMethod(anyString())).thenReturn(200);
//throw an exception
when(mock.someMethod("some argument")).thenThrow(new RuntimeException());
```
- [`spy()`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#spy-T-)/ [`@Spy`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Spy.html)- It is used for partial mocking. It means that the real methods are invoked but still can be verified and stubbed.
- There are few more methods and annotations available, such as [`@InjectMocks`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/InjectMocks.html),[` verify()`](http://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#verify-T-)
Note that if a project contains private methods to test, then we can't use Mockito as it does not mock private methods. Mockito assumes that private methods don't exist from the viewpoint of testing.
There are few other mocking frameworks available for Java, such as [JMock](http://www.jmock.org/), [EasyMock](http://easymock.org/), and [Powermock](https://powermock.github.io/). It is a matter of choice of the developer based on preferences such as Powermock can even mock private methods.
**Writing the UserController class**
{%youtube QPDYREKOwR4%}
## ShannonNote
https://hackmd.io/@ShannonHung/SynzguiIP
# 10 Best Practice
**Unit Testing Best Practices**
{%youtube 7jAekgd00PM%}
**Further reading**
{%youtube mSXHlyKXlno%}
Here are the topics mentioned in the above video, which you may want to consider diving into when you have time:
- [Exceptions](https://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html)
- [Writing Great Unit Tests](https://stormpath.com/blog/7-tips-writing-unit-tests-java)
- [Advanced Mockito](https://www.vogella.com/tutorials/Mockito/article.html)
- [PowerMock](https://powermock.github.io/)
- [TestNg](https://testng.org/doc/)
**Conclusion**
We have studied the following topics, as promised at the beginning of this lesson:
- Basics of software testing
- Details of unit testing
- Introduction to JUnits framework
- Writing JUnit test using annotations
- Creating mocks for unit test, using Mockito framework
- Adding tests for the authentication component previously developed in the eCommerce Application