-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathunit-testing.qmd
More file actions
155 lines (124 loc) · 4.54 KB
/
Copy pathunit-testing.qmd
File metadata and controls
155 lines (124 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
---
title: Unit testing
description: How to ensure high quality components.
order: 50
---
{{< include ../../_includes/_language_chooser.qmd >}}
```{r setup, include=FALSE}
repo_path <- system("git rev-parse --show-toplevel", intern = TRUE)
source(paste0(repo_path, "/_includes/_r_helper.R"))
source(paste0(repo_path, "/guide/component/_language_examples.R"))
langs <- langs %>%
mutate(
label = gsub("#", "\\\\#", label)
)
```
We recommend adding unit tests to all of your components in a project as soon as possible.
Implementing unit tests not only ensures that your component works, but it also makes
the project more maintainable in the long run as you will be notified when a component breaks.
This page describes how to add a unit test to your component.
```{r setup-adding-resources, include=FALSE}
temp_dir <- tempfile("unit-testing")
dir.create(temp_dir, recursive = TRUE, showWarnings = FALSE)
on.exit(unlink(temp_dir, recursive = TRUE), add = TRUE)
# create tempdir with modified files
add_unit_test <- function(config, type, path) {
# add helper to resources
config$test_resources <- list(
list(type = type, path = path)
)
config
}
langs <- langs %>%
mutate(
example_test = gsub("script", "test", example_script),
config_path = paste0(temp_dir, "/", id, "/", basename(example_config)),
script_path = paste0(temp_dir, "/", id, "/", basename(example_script)),
test_path = paste0(temp_dir, "/", id, "/", basename(example_test)),
)
pwalk(langs, function(id, script_type, example_config, example_script, example_test, config_path, script_path, test_path, ...) {
# create dir
dir.create(paste0(temp_dir, "/", id), recursive = TRUE, showWarnings = FALSE)
# read config, make modifications, write to file
conf <- yaml::read_yaml(example_config) %>%
add_unit_test(script_type, basename(test_path))
write_yaml(conf, config_path)
# copy script
file.copy(example_script, script_path)
file.copy(example_test, test_path)
})
```
## Create unit test
Below is an example of how to add a unit test to a Viash component.
::: {.panel-tabset}
```{r show-helper, output="asis"}
pwalk(langs, function(id, label, test_path, ...) {
qrt(
"## {% label %}
|
|```{% id %}
|{% paste(readr::read_lines(test_path), collapse = '\n') %}
|```
|
|")
})
```
:::
1. Create an input file "foo.txt" with some sample content.
2. Run an executable file specified in the "meta" dictionary with the arguments "--input foo.txt" and "--output bar.txt".
3. Check whether the output file "bar.txt" exists.
4. Check whether the content of the output file is the same as the content of the input file.
5. If both checks pass, the script prints "Test finished successfully".
:::{.callout-important}
A test script doesn't need to be written in the same scripting language as the main script, as long as all of the required dependencies are available. This means the main script could be written in R, but the unit test could be written in Bash.
:::
## Add test to config
Next, we need to add the unit test to the `test_resources` section in the Viash config.
::: {.panel-tabset}
```{r show-config, output="asis"}
pwalk(langs, function(id, label, config_path, script_path, ...) {
qrt(
"## {% label %}
|
|```yaml
|{% paste(readr::read_lines(config_path), collapse = '\n |') %}
|```
|")
})
```
:::
Note that if you can add multiple unit tests to the `test_resources` section,
they will all be evaluated. You can also add other resources, similar to
what is described in the page on [adding resources](add-resources.qmd).
## Run the unit test
You can run the unit test as follows:
::: {.panel-tabset}
```{r echo=FALSE, output="asis"}
pwalk(langs, function(id, label, config_path, script_path, ...) {
qrt(
"## {% label %}
|
|```{bash test-example}
|viash test config.vsh.yaml
|```
|",
.dir = paste0(temp_dir, "/", id)
)
})
```
:::
When running `viash test`, Viash will follow the following steps:
1. Create a temporary directory
2. Build the component into the main executable
3. (Re-)build the Docker image for the component
4. Iterate over all unit test scripts:
a. Build the unit test into an executable
b. Run the unit test, passing the main executable as an argument
5. Return exit code 0 if all of the above steps succeed, otherwise 0
## Bonus: unit testing all of the components
If you have multiple Viash components located in a directory
called `src/`, what happens when you run the following?
```bash
viash ns test --parallel --src src/
```
{{< include ../../_includes/_prune_all_images.qmd >}}