... |
... |
@@ -15,7 +15,7 @@ |
15 |
15 |
* **Documentation** |
16 |
16 |
** **Always Up To Date**: Tests serve as the most up-to-date form of code documentation, capturing the expected behavior of the production code in its current state or of a third-party library. |
17 |
17 |
** **Code Is Best Documentation**: Good tests are quick and easy to understand because they are written in an expressive language that developers speak fluently. In addition, the actual documentation with its long texts is often skipped anyway. |
18 |
|
-** **Behavior Is Easier To Understand Than Implementation**: Tests are a clearer representation of behavior than the implementation itself. Tests specify the input for a given code and assert the expected output, providing an intuitive understanding that's easier to grasp than the intricacies concrete, low-level implementations. Simply put, what code does is easier to understand than how it does it. |
|
18 |
+** **Behavior Is Easier To Understand Than Implementation**: Tests are a clearer representation of behavior than the implementation itself. Tests specify the input for a given code and assert the expected output, providing an intuitive understanding that's easier to grasp than the intricacies of production code. Simply put, what code does is easier to understand than how it does it. |
19 |
19 |
|
20 |
20 |
=== What should be tested? === |
21 |
21 |
|
... |
... |
@@ -24,12 +24,12 @@ |
24 |
24 |
|
25 |
25 |
* **High-level business use cases** defined by the customer in project requirements. Tests are essentially requirements translated into code. And customer requirements are typically translated into [[Acceptance Tests>>doc:Software Engineering.Agile.Extreme Programming.Acceptance Tests.WebHome]]. |
26 |
26 |
* **Lower-level technical use cases** derived from high-level business use cases that are not directly visible to end users, but form the backbone of software functionality. This includes the expected behavior of the underlying components, modules and units. |
27 |
|
-* **Border cases** that could theoretically occur, such as maximum/minimum values, nulls, invalid input outside the permissible value range, zeroes, negative numbers, empty lists, values with special meaning, exceptions, etc. |
28 |
|
-* If needed: |
29 |
|
-** **Performance requirements** |
30 |
|
-** **Security requirements** |
31 |
|
-** **Load requirements**, when software is expected to handle a certain number of requests per second. |
32 |
|
-* At any level of abstraction, you should always test **happy path** requirements, where everything works as expected, and **unhappy path** requirements, where something goes wrong or an unusual input is provided. Writing tests for the latter makes the software robust against failures and misuse. |
|
27 |
+* You should always test **happy path** requirements, where a user story works as expected, and **unhappy path** requirements. For the latter, we need **chaos engineering**, i.e., verifying that a system can withstand unusual conditions makes it robust against failure and misuse. |
|
28 |
+** **Border cases** that could theoretically occur, such as maximum/minimum values, nulls, invalid input outside the permissible value range, zeroes, negative numbers, empty lists, values with special meaning. |
|
29 |
+** For example, at the operational level, this could include actions such as killing processes, shutting down servers, disconnecting networks, even simulating entire data center failures due to disasters, etc., while verifying that the system is still fully functional, available, and able to automatically recover. |
|
30 |
+** **Security requirements**: For example, simulate all potential attack scenarios and verify that the software can withstand them. |
|
31 |
+* **Performance requirements**: Interactions with software often need to be completed in a certain amount of time. |
|
32 |
+* **Load requirements**, when software is expected to handle a certain number of requests per second. |
33 |
33 |
|
34 |
34 |
=== Table of Contents === |
35 |
35 |
|