Skip to content

Commit 4bd2607

Browse files
[docs] explainer for java packaging tests (elastic#30825)
1 parent e8b7027 commit 4bd2607

File tree

2 files changed

+121
-3
lines changed

2 files changed

+121
-3
lines changed

qa/vagrant/README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# packaging tests
2+
3+
This project contains tests that verify the distributions we build work
4+
correctly on the operating systems we support. They're intended to cover the
5+
steps a user would take when installing and configuring an Elasticsearch
6+
distribution. They're not intended to have significant coverage of the behavior
7+
of Elasticsearch's features.
8+
9+
There are two types of tests in this project. The old tests live in
10+
`src/test/` and are written in [Bats](https://github.com/sstephenson/bats),
11+
which is a flavor of bash scripts that run as unit tests. These tests are
12+
deprecated because Bats is unmaintained and cannot run on Windows.
13+
14+
The new tests live in `src/main/` and are written in Java. Like the old tests,
15+
this project's tests are run inside the VM, not on your host. All new packaging
16+
tests should be added to this set of tests if possible.
17+
18+
## Running these tests
19+
20+
See the section in [TESTING.asciidoc](../../TESTING.asciidoc#testing-packaging)
21+
22+
## Adding a new test class
23+
24+
When gradle runs the packaging tests on a VM, it runs the full suite by
25+
default. To add a test class to the suite, add its `class` to the
26+
`@SuiteClasses` annotation in [PackagingTests.java](src/main/java/org/elasticsearch/packaging/PackagingTests.java).
27+
If a test class is added to the project but not to this annotation, it will not
28+
run in CI jobs. The test classes are run in the order they are listed in the
29+
annotation.
30+
31+
## Choosing which distributions to test
32+
33+
Distributions are represented by [enum values](src/main/java/org/elasticsearch/packaging/util/Distribution.java)
34+
which know if they are compatible with the platform the tests are currently
35+
running on. To skip a test if the distribution it's using isn't compatible with
36+
the current platform, put this [assumption](https://github.com/junit-team/junit4/wiki/assumptions-with-assume)
37+
in your test method or in a `@Before` method
38+
39+
```java
40+
assumeTrue(distribution.packaging.compatible);
41+
```
42+
43+
Similarly if you write a test that is intended only for particular platforms,
44+
you can make an assumption using the constants and methods in [Platforms.java](src/main/java/org/elasticsearch/packaging/util/Platforms.java)
45+
46+
```java
47+
assumeTrue("only run on windows", Platforms.WINDOWS);
48+
49+
assumeTrue("only run if using systemd", Platforms.isSystemd());
50+
```
51+
52+
## Writing a test that covers multiple distributions
53+
54+
It seems like the way to do this that makes it the most straightforward to run
55+
and reproduce specific test cases is to create a test case class with an
56+
abstract method that provides the distribution
57+
58+
```java
59+
public abstract class MyTestCase {
60+
@Test
61+
public void myTest() { /* do something with the value of #distribution() */ }
62+
abstract Distribution distribution();
63+
}
64+
```
65+
66+
and then for each distribution you want to test, create a subclass
67+
68+
```java
69+
public class MyTestDefaultTar extends MyTestCase {
70+
@Override
71+
Distribution distribution() { return Distribution.DEFAULT_TAR; }
72+
}
73+
```
74+
75+
That way when a test fails the user gets told explicitly that `MyTestDefaultTar`
76+
failed, and to reproduce it they should run that class. See [ArchiveTestCase](src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java)
77+
and its children for an example of this.
78+
79+
## Running external commands
80+
81+
In general it's probably best to avoid running external commands when a good
82+
Java alternative exists. For example most filesystem operations can be done with
83+
the java.nio.file APIs. For those that aren't, use an instance of [Shell](src/main/java/org/elasticsearch/packaging/util/Shell.java)
84+
85+
Despite the name, commands run with this class are not run in a shell, and any
86+
familiar features of shells like variables or expansion won't work.
87+
88+
If you do need the shell, you must explicitly invoke the shell's command. For
89+
example to run a command with Bash, use the `bash -c command` syntax. Note that
90+
the entire script must be in a single string argument
91+
92+
```java
93+
Shell sh = new Shell();
94+
sh.run("bash", "-c", "echo $foo; echo $bar");
95+
```
96+
97+
Similary for powershell - again, the entire powershell script must go in a
98+
single string argument
99+
100+
```java
101+
sh.run("powershell.exe", "-Command", "Write-Host $foo; Write-Host $bar");
102+
```
103+
104+
On Linux, most commands you'll want to use will be executable files and will
105+
work fine without a shell
106+
107+
```java
108+
sh.run("tar", "-xzpf", "elasticsearch-6.1.0.tar.gz");
109+
```
110+
111+
On Windows you'll mostly want to use powershell as it can do a lot more and
112+
gives much better feedback than Windows' legacy command line. Unfortunately that
113+
means that you'll need to use the `powershell.exe -Command` syntax as
114+
powershell's [Cmdlets](https://msdn.microsoft.com/en-us/library/ms714395.aspx)
115+
don't correspond to executable files and are not runnable by `Runtime` directly.
116+
117+
When writing powershell commands this way, make sure to test them as some types
118+
of formatting can cause it to return a successful exit code but not run
119+
anything.

qa/vagrant/src/main/java/org/elasticsearch/packaging/test/ArchiveTestCase.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
import static org.elasticsearch.packaging.util.Cleanup.cleanEverything;
3232
import static org.elasticsearch.packaging.util.Archives.installArchive;
3333
import static org.elasticsearch.packaging.util.Archives.verifyArchiveInstallation;
34-
import static org.hamcrest.CoreMatchers.is;
35-
import static org.junit.Assume.assumeThat;
34+
import static org.junit.Assume.assumeTrue;
3635

3736
/**
3837
* Tests that apply to the archive distributions (tar, zip). To add a case for a distribution, subclass and
@@ -54,7 +53,7 @@ public static void cleanup() {
5453

5554
@Before
5655
public void onlyCompatibleDistributions() {
57-
assumeThat(distribution().packaging.compatible, is(true));
56+
assumeTrue("only compatible distributions", distribution().packaging.compatible);
5857
}
5958

6059
@Test

0 commit comments

Comments
 (0)