2023-10-06 15:54:38 +02:00
---
2023-10-09 09:03:54 +02:00
type: slide
slideOptions:
transition: slide
width: 1400
height: 900
margin: 0.1
2023-10-06 15:54:38 +02:00
---
2023-10-09 09:03:54 +02:00
< style >
.reveal strong {
font-weight: bold;
color: orange;
}
.reveal p {
text-align: left;
}
.reveal section h1 {
color: orange;
}
.reveal section h2 {
color: orange;
}
.reveal code {
font-family: 'Ubuntu Mono';
color: orange;
}
.reveal section img {
background:none;
border:none;
box-shadow:none;
}
< / style >
2023-10-06 15:54:38 +02:00
# Learning Goals
- Get to know a few common terms of testing
- Work with the Julia unit testing package `Test.jl`
2023-10-09 15:49:03 +02:00
Material is taken and modified from the [SSE lecture ](https://github.com/Simulation-Software-Engineering/Lecture-Material ), which builds partly on the [py-rse book ](https://merely-useful.tech/py-rse ), and from the [Test.jl docs ](https://docs.julialang.org/en/v1/stdlib/Test/ ).
2023-10-06 15:54:38 +02:00
---
# 1. General Introduction to Testing
---
## What is Testing?
2023-10-09 15:49:03 +02:00
- Smelling old milk before using it
- A way to determine if a software is not producing reliable results and if so, what is the reason
- Manual testing vs. automated testing
2023-10-06 15:54:38 +02:00
---
## Why Should you Test your Software?
2023-10-09 15:49:03 +02:00
- Improve software reliability and reproducibility
- Make sure that changes (bugfixes, new features) do not affect other parts of software
2023-10-06 15:54:38 +02:00
- Generally all software is better off being tested regularly. Possible exceptions are very small codes with single users.
- Ensure that a released version of a software actually works.
---
## Some Ways to Test Software
- Assertions
- Unit testing
- Integration testing
- Regression testing
---
## Assertions
2023-10-09 15:49:03 +02:00
```julia
@assert condition "message"
```
- Principle of *defensive programming*
2023-10-06 15:54:38 +02:00
- Nothing happens when an assertion is true; throws error when false.
- Types of assertion statements:
- Precondition
- Postcondition
- Invariant
2023-10-09 15:49:03 +02:00
- A basic but powerful tool to test a software on-the-go
2023-10-06 15:54:38 +02:00
---
## Unit Testing
2023-10-09 15:49:03 +02:00
- Catching errors with assertions is good but preventing them is better.
2023-10-06 15:54:38 +02:00
- A *unit* is a single function in one situation.
- A situation is one amongst many possible variations of input parameters.
2023-10-09 15:49:03 +02:00
- User creates the **expected result** manually.
- **Actual result** is compared to the expected result by `@test` .
2023-10-06 15:54:38 +02:00
---
## Integration Testing
- Test whether several units work in conjunction.
- *Integrate* units and test them together in an *integration* test.
2023-10-09 15:49:03 +02:00
- Often more complicated than a unit test and gives higher test coverage.
2023-10-06 15:54:38 +02:00
---
## Regression Testing
- Generating an expected result is not possible in some situations.
2023-10-09 15:49:03 +02:00
- Compare the *current* actual result with a *previous* actual result.
2023-10-06 15:54:38 +02:00
- No guarantee that the current actual result is correct.
- Risk of a bug being carried over indefinitely.
- Main purpose is to identify changes in the current state of the code with respect to a past state.
---
# 2. Unit Testing in Julia with Test.jl
---
2023-10-09 15:49:03 +02:00
## Setup of Test.jl
2023-10-06 15:54:38 +02:00
- Standardized folder structure:
2023-10-09 15:49:03 +02:00
```
├── Manifest.toml
├── Project.toml
├── src/
└── test
├── Manifest.toml
├── Project.toml
├── runtests.jl
└── setup.jl
```
2023-10-06 15:54:38 +02:00
- Singular `test` vs plural `runtests.jl`
- `setup.jl` for all `using XYZ` statements, included in `runtests.jl`
2023-10-09 15:49:03 +02:00
- Additional packages in `[extra] section` of `./Project.toml` or in new `./test/Project.toml`
2023-10-06 15:54:38 +02:00
- In case of the latter: Do not add the package itself to the `./test/Project.toml`
2023-10-09 15:49:03 +02:00
- Run: `]test` when root project is activated
2023-10-06 15:54:38 +02:00
---
## Implement and Structure Tests
- `@test expr` : Test whether expression `expr` is true
- `@test expr broken=true` : Explicitly mark test as broken
- `@test_throws exception expr` : Test whether expression `expr` throws `exception` (test unhappy path)
```julia
julia> @test_throws DimensionMismatch [1, 2, 3] + [1, 2]
Test Passed
Thrown: DimensionMismatch
```
- `@testset` : Structure tests
```julia
2023-10-09 15:49:03 +02:00
@testset "trigonometric identities" begin
θ = 2/3*π
@test sin(-θ) ≈ -sin(θ)
@test cos(-θ) ≈ cos(θ)
end;
2023-10-06 15:54:38 +02:00
```
- `@testset for ... end` : Test in loop
---
## Further Reading and Watching
- [Research Software Engineering with Python - Chapter 11: Testing Software ](https://merely-useful.tech/py-rse/testing.html )
- [HiRSE-Summer of Testing Part 2b: "Testing with Julia" by Nils Niggemann ](https://www.youtube.com/watch?v=gSMKNbZOpZU )
- [Official documentation of Test.jl ](https://docs.julialang.org/en/v1/stdlib/Test/ )
2023-10-09 15:49:03 +02:00
---
2023-10-06 15:54:38 +02:00
# 3. Test.jl Demo
We use [`MyTestPackage` ](https://github.com/s-ccs/summerschool_simtech_2023/tree/main/material/2_tue/testing/MyTestPackage ), which looks as follows:
```
├── Manifest.toml
├── Project.toml
├── src
│ ├── find.jl
│ └── MyTestPackage.jl
└── test
├── find.jl
├── Manifest.toml
├── Project.toml
├── runtests.jl
└── setup.jl
```
- Look at `MyTestPackage.jl` and `find.jl` : We have two functions `find_max` and `find_mean` , which calculate the maximum and mean of all elements of a `::AbstractVector` .
- Assertions were added to check for `NaN` values
- Look at `runtests.jl` :
2023-10-09 15:49:03 +02:00
- Why do we need `using MyTestPackage` ?
2023-10-06 15:54:38 +02:00
- We include dependencies via `setup.jl` : `Test` and `StableRNG` .
- Testset "find"
- Look at `find.jl`
- Unit tests for `find_max` and `find_mean`
- `test_throws` to test unhappy path
- Test with absolute tolerance
- Integration test, which tests combination of both methods
- Run tests:
```
]activate .
]test
```
---
# 4. Exercise
Write tests for your own statistics package 😊