11
11
12
12
` gdt ` is a testing library that allows test authors to cleanly describe tests
13
13
in a YAML file. ` gdt ` reads YAML files that describe a test's assertions and
14
- then builds a set of Golang structures that the standard Golang
14
+ then builds a set of Go structures that the standard Go
15
15
[ ` testing ` ] ( https://golang.org/pkg/testing/ ) package and standard ` go test `
16
16
tool can execute.
17
17
18
18
## Introduction
19
19
20
- Writing functional tests in Golang can be overly verbose and tedious. When the
21
- code that tests some part of an application is verbose or tedious, then it
22
- becomes difficult to read the tests and quickly understand the assertions the
23
- test is making.
20
+ Writing functional tests in Go can be overly verbose and tedious. When the code
21
+ that tests some part of an application is verbose or tedious, then it becomes
22
+ difficult to read the tests and quickly understand the assertions the test is
23
+ making.
24
24
25
25
The more difficult it is to understand the test assertions or the test setups
26
26
and assumptions, the greater the chance that the test improperly validates the
@@ -34,7 +34,7 @@ describe a functional test's **assumptions** and **assertions** in a
34
34
declarative format.
35
35
36
36
Separating the * description* of a test's assumptions (setup) and assertions
37
- from the Golang code that actually performs the test assertions leads to tests
37
+ from the Go code that actually performs the test assertions leads to tests
38
38
that are easier to read and understand. This allows developers to spend * more
39
39
time writing code* and less time copy/pasting boilerplate test code. Due to the
40
40
easier test comprehension, ` gdt ` also encourages writing greater quality and
@@ -138,9 +138,9 @@ var _ = Describe("Books API Types", func() {
138
138
` ` `
139
139
140
140
141
- This is perfectly fine for simple unit tests of Golang code. However, once the
142
- tests begin to call multiple APIs or packages, the Ginkgo Golang tests start to
143
- get cumbersome. Consider the following example of *functionally* testing the
141
+ This is perfectly fine for simple unit tests of Go code. However, once the
142
+ tests begin to call multiple APIs or packages, the Ginkgo Go tests start to get
143
+ cumbersome. Consider the following example of *functionally* testing the
144
144
failure modes for a simple HTTP REST API endpoint
145
145
([`failure_test.go`](https://github.com/gdt-dev/gdt-examples/blob/main/http/api/failure_test.go)) :
146
146
@@ -256,7 +256,7 @@ var _ = Describe("Books API - GET /books failures", func() {
256
256
` ` `
257
257
258
258
The above test code obscures what is being tested by cluttering the test
259
- assertions with the Golang closures and accessor code. Compare the above with
259
+ assertions with the Go closures and accessor code. Compare the above with
260
260
how `gdt` allows the test author to describe the same assertions
261
261
([`failures.yaml`](https://github.com/gdt-dev/gdt-examples/blob/main/http/tests/api/failures.yaml)) :
262
262
@@ -284,7 +284,7 @@ No more closures and boilerplate function code getting in the way of expressing
284
284
the assertions, which should be the focus of the test.
285
285
286
286
The more intricate the assertions being verified by the test, generally the
287
- more verbose and cumbersome the Golang test code tends to become. First and
287
+ more verbose and cumbersome the Go test code tends to become. First and
288
288
foremost, tests should be *readable*. If they are not readable, then the test's
289
289
assertions are not *understandable*. And tests that cannot easily be understood
290
290
are often the source of bit rot and technical debt. Worse, tests that aren't
@@ -300,7 +300,7 @@ Consider a Ginkgo test case that checks the following behaviour:
300
300
* The newly-created book's ID field is a valid UUID
301
301
* The newly-created book's publisher has an address containing a known state code
302
302
303
- A typical implementation of a Ginkgo Golang test might look like this
303
+ A typical implementation of a Ginkgo test might look like this
304
304
([`create_then_get_test.go`](https://github.com/gdt-dev/gdt-examples/blob/main/http/api/create_then_get_test.go)) :
305
305
306
306
` ` ` go
@@ -423,8 +423,7 @@ All `gdt` scenarios have the following fields:
423
423
missing or empty, the filename is used as the name
424
424
* `description`: (optional) string with longer description of the test file
425
425
contents
426
- * `defaults`: (optional) is a map, keyed by a plugin name, of default options
427
- and configuration values for that plugin.
426
+ * `defaults`: (optional) is a map of default options and configuration values
428
427
* `fixtures`: (optional) list of strings indicating named fixtures that will be
429
428
started before any of the tests in the file are run
430
429
* `skip-if`: (optional) list of [`Spec`][basespec] specializations that will be
@@ -433,26 +432,29 @@ All `gdt` scenarios have the following fields:
433
432
* `tests`: list of [`Spec`][basespec] specializations that represent the
434
433
runnable test units in the test scenario.
435
434
436
- [basespec] : https://github.com/gdt-dev/gdt/blob/2791e11105fd3c36d1f11a7d111e089be7cdc84c /types/spec.go#L27-L44
435
+ [basespec] : https://github.com/gdt-dev/gdt/blob/ecee17249e1fa10147cf9191be0358923da44094 /types/spec.go#L30
437
436
438
437
The scenario's `tests` field is the most important and the [`Spec`][basespec]
439
438
objects that it contains are the meat of a test scenario.
440
439
441
- # # `gdt` test spec structure
440
+ # ## `gdt` test spec structure
442
441
443
442
A spec represents a single *action* that is taken and zero or more
444
443
*assertions* that represent what you expect to see resulting from that action.
445
444
446
- Each spec is a specialized class of the base [`Spec`][basespec] that deals with
447
- a particular type of test. For example, there is a `Spec` class called `exec`
448
- that allows you to execute arbitrary commands and assert expected result codes
449
- and output. There is a `Spec` class called `http` that allows you to call an
450
- HTTP URL and assert that the response looks like what you expect. Depending on
451
- how you define your test units, `gdt` will parse the YAML definition into one
452
- of these specialized `Spec` classes.
445
+ ` gdt` plugins each define a specialized subclass of the base [`Spec`][basespec]
446
+ that contains fields that are specific to that type of test.
453
447
454
- The base `Spec` class has the following fields (and thus all `Spec` specialized
455
- classes inherit these fields) :
448
+ For example, there is an [`exec`][exec-plugin] plugin that allows you to
449
+ execute arbitrary commands and assert expected result codes and output. There
450
+ is an [`http`][http-plugin] that allows you to call an HTTP URL and assert that
451
+ the response looks like what you expect. There is a [`kube`][kube-plugin]
452
+ plugin that allows you to interact with a Kubernetes API, etc.
453
+
454
+ ` gdt` examines the YAML file that defines your test scenario and uses these
455
+ plugins to parse individual test specs.
456
+
457
+ All test specs have the following fields :
456
458
457
459
* `name`: (optional) string describing the test unit.
458
460
* `description`: (optional) string with longer description of the test unit.
@@ -462,24 +464,49 @@ classes inherit these fields):
462
464
complete within.
463
465
* `timeout.expected`: a bool indicating that the test unit is expected to not
464
466
complete before `timeout.after`. This is really only useful in unit testing.
467
+ * `retry`: (optional) an object containing retry configurationu for the test
468
+ unit. Some plugins will automatically attempt to retry the test action when
469
+ an assertion fails. This field allows you to control this retry behaviour for
470
+ each individual test.
471
+ * `retry.interval`: (optional) a string duration of time that the test plugin
472
+ will retry the test action in the event assertions fail. The default interval
473
+ for retries is plugin-dependent.
474
+ * `retry.attempts`: (optional) an integer indicating the number of times that a
475
+ plugin will retry the test action in the event assertions fail. The default
476
+ number of attempts for retries is plugin-dependent.
477
+ * `retry.exponential`: (optional) a boolean indicating an exponential backoff
478
+ should be applied to the retry interval. The default is is plugin-dependent.
465
479
* `wait` (optional) an object containing [wait information][wait] for the test
466
480
unit.
467
481
* `wait.before`: a string duration of time that gdt should wait before
468
482
executing the test unit's action.
469
483
* `wait.after`: a string duration of time that gdt should wait after executing
470
484
the test unit's action.
485
+ * `on`: (optional) an object describing actions to take upon certain
486
+ conditions.
487
+ * `on.fail`: (optional) an object describing an action to take when any
488
+ assertion fails for the test action.
489
+ * `on.fail.exec`: a string with the exact command to execute upon test
490
+ assertion failure. You may execute more than one command but must include the
491
+ ` on.fail.shell` field to indicate that the command should be run in a shell.
492
+ * `on.fail.shell`: (optional) a string with the specific shell to use in executing the
493
+ command to run upon test assertion failure. If empty (the default), no shell
494
+ is used to execute the command and instead the operating system's `exec` family
495
+ of calls is used.
471
496
497
+ [exec-plugin] : https://github.com/gdt-dev/gdt/tree/ecee17249e1fa10147cf9191be0358923da44094/plugin/exec
498
+ [http-plugin] : https://github.com/gdt-dev/http
499
+ [kube-plugin] : https://github.com/gdt-dev/kube
472
500
[timeout] : https://github.com/gdt-dev/gdt/blob/2791e11105fd3c36d1f11a7d111e089be7cdc84c/types/timeout.go#L11-L22
473
501
[wait] : https://github.com/gdt-dev/gdt/blob/2791e11105fd3c36d1f11a7d111e089be7cdc84c/types/wait.go#L11-L25
474
502
475
- # ## `exec` test spec structure
503
+ # ### `exec` test spec structure
476
504
477
- An exec spec is a specialization of the base [`Spec`][basespec] that allows
478
- test authors to execute arbitrary commands and assert that the command results
479
- in an expected result code or output.
505
+ The `exec` plugin's test spec allows test authors to execute arbitrary commands and
506
+ assert that the command results in an expected result code or output.
480
507
481
- The [exec `Spec`][execspec] class has the following fields (in addition to all
482
- the base `Spec` fields listed above) :
508
+ In addition to all the base `Spec` fields listed above, the `exec` plugin's
509
+ test spec also contains these fields :
483
510
484
511
* `exec`: a string with the exact command to execute. You may execute more than
485
512
one command but must include the `shell` field to indicate that the command
@@ -514,17 +541,6 @@ the base `Spec` fields listed above):
514
541
least one* must be present in `stderr`.
515
542
* `assert.err.none`: (optional) a string or list of strings of which *none
516
543
should be present* in `stderr`.
517
- * `on`: (optional) an object describing actions to take upon certain
518
- conditions.
519
- * `on.fail`: (optional) an object describing an action to take when any
520
- assertion fails for the test action.
521
- * `on.fail.exec`: a string with the exact command to execute upon test
522
- assertion failure. You may execute more than one command but must include the
523
- ` on.fail.shell` field to indicate that the command should be run in a shell.
524
- * `on.fail.shell`: (optional) a string with the specific shell to use in executing the
525
- command to run upon test assertion failure. If empty (the default), no shell
526
- is used to execute the command and instead the operating system's `exec` family
527
- of calls is used.
528
544
529
545
[execspec] : https://github.com/gdt-dev/gdt/blob/2791e11105fd3c36d1f11a7d111e089be7cdc84c/exec/spec.go#L11-L34
530
546
[pipeexpect] : https://github.com/gdt-dev/gdt/blob/2791e11105fd3c36d1f11a7d111e089be7cdc84c/exec/assertions.go#L15-L26
@@ -533,7 +549,7 @@ the base `Spec` fields listed above):
533
549
534
550
` gdt` was inspired by [Gabbi](https://github.com/cdent/gabbi), the excellent
535
551
Python declarative testing framework. `gdt` tries to bring the same clear,
536
- concise test definitions to the world of Golang functional testing.
552
+ concise test definitions to the world of Go functional testing.
537
553
538
554
The Go gopher logo, from which gdt's logo was derived, was created by Renee
539
555
French.
0 commit comments