Random methods public void testRandomStringLength() { String randomString = randomAlphaOfLength(10); assertThat(randomString.length(), is(10)); boolean randomBoolean = randomBoolean(); assertThat(randomBoolean, is(anyOf(is(true), is(false)))); final Integer randomInt = randomFrom(1, 22, 11, 41, 58); assertThat(randomInt, is(allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(58)))); final int randomIntBetween = randomIntBetween(1, 10); assertThat(randomIntBetween, is(allOf(greaterThanOrEqualTo(1), lessThanOrEqualTo(10)))); final long nonNegativeLong = randomNonNegativeLong(); assertThat(nonNegativeLong, is(greaterThanOrEqualTo(0L))); final ZoneId zoneId = randomZone(); assertThat(ZoneId.getAvailableZoneIds(), hasItem(zoneId.toString())); final Locale locale = randomLocale(random()); assertThat(Arrays.asList(Locale.getAvailableLocales()), hasItem(locale)); }
Slide 18
Random methods public void testRandomStringLength() { String randomString = randomAlphaOfLength(10); assertThat(randomString.length(), is(10)); }
Slide 19
Random methods public void testRandomStringLength() { String randomString = randomAlphaOfLength(10); assertThat(randomString.length(), is(10)); } public void testRandomStringLength() { String randomString = randomAlphaOfLength(10); assertThat(randomString.length(), is(Integer.MAX_VALUE)); }
Slide 20
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; }
Slide 21
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } public void testAdd() { assertThat(add(1, 1), is(2)); assertThat(add(2, 2), is(4)); }
Slide 22
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } public void testAdd() { final int a = randomIntBetween(0, Integer.MAX_VALUE); final int b = randomIntBetween(0, Integer.MAX_VALUE); assertThat(add(a, b), allOf(greaterThanOrEqualTo(a), greaterThanOrEqualTo(b))); }
Slide 23
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } @Repeat(iterations = 1000) public void testAdd() { final int a = randomIntBetween(0, Integer.MAX_VALUE); final int b = randomIntBetween(0, Integer.MAX_VALUE); assertThat(add(a, b), allOf(greaterThanOrEqualTo(a), greaterThanOrEqualTo(b))); }
Slide 24
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } @Repeat(iterations = 1000) public void testAdd() { final int a = randomIntBetween(0, Integer.MAX_VALUE); final int b = randomIntBetween(0, Integer.MAX_VALUE); assertThat(add(a, b), allOf(greaterThanOrEqualTo(a), greaterThanOrEqualTo(b))); }
java.lang.AssertionError: Expected: (a value equal to or greater than <1667057423> and a value equal to or greater than <1800656534>) but: a value equal to or greater than <1667057423> <-827253339> was less than <1667057423>
Slide 25
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } @Repeat(iterations = 1000) public void testAdd() { final int a = randomIntBetween(0, Integer.MAX_VALUE); final int b = randomIntBetween(0, Integer.MAX_VALUE); assertThat(add(a, b), allOf(greaterThanOrEqualTo(a), greaterThanOrEqualTo(b))); }
REPRODUCE WITH: ./gradlew ‘:server:test’ —tests “de.spinscale.MyTest.testAdd” -Dtests.seed=EC29A319F9128F9A -Dtests.locale=pl-PL -Dtests.timezone=America/St_Kitts
Slide 26
Randomization Example private int add (int a, int b) { assert a > 0; assert b > 0; return a + b; } @Seed(“EC29A319F9128F9A”) public void testAdd() { final int a = randomIntBetween(0, Integer.MAX_VALUE); final int b = randomIntBetween(0, Integer.MAX_VALUE); assertThat(add(a, b), allOf(greaterThanOrEqualTo(a), greaterThanOrEqualTo(b))); }
Slide 27
ESTestCase goodies Thread leak detection Change log level for single test/package Checks for excessive sysout/err writes Test method order is randomized Test class order is randomized Deprecation logging checks No inflight search contexts
Slide 28
Integration Testing YAML ftw!
Slide 29
HTTP Integration tests Run tests against Elasticsearch HTTP interface Tests are written in YAML API definition is written in JSON ESClientYamlSuiteTestCase to extend All official clients are using the same spec to guarantee feature parity
Slide 30
API definition {
}
“get”:{ “documentation”:{ “url”:”https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html”, “description”:”Returns a document.” }, “stability”:”stable”, “url”:{ “paths”:[ { “path”:”/{index}/_doc/{id}”, “methods”:[ “GET” ], “parts”:{ “id”:{ “type”:”string”, “description”:”The document ID” }, “index”:{ “type”:”string”, “description”:”The name of the index” } } } ] }, “params”:{ “preference”:{ “type”:”string”, “description”:”Specify the node or shard the operation should be performed on (default: random)” } … } }
More integration testing Test against kerberos/samba/openldap/shibboleth-idp using docker and docker-compose S3 integration testing using minio (via dockercompose) Testing the docker image via docker-compose
Slide 33
Package Testing Containers
Slide 34
Elasticsearch: A lot of flavours tar.gz, zip, deb, rpm apt / yum repositories docker images osx brew tap Windows MSI helm chart, ECK (K8s operator) puppet, ansible, chef
Testing packages bats is used for testing bats: bash automated testing package installation/start/stop/uninstall Long term plan: Moving away from bats to java tests
https://github.com/elastic/elasticsearch/tree/master/qa/os
Slide 37
BWC Testing You get an upgrade, everyone gets an upgrade!
Slide 38
BWC Testing Upgrades must be supported and tested! Full cluster restart Rolling restarts between minor versions Rolling restarts from the latest old major version to the current major version, i.e. 6.8.4 to 7.4.1
Slide 39
Rolling upgrade tests
6.8.x
6.8.x
6.8.x
Slide 40
Rolling upgrade tests
6.8.x
6.8.x
6.8.x
Slide 41
Rolling upgrade tests upgrade 7.4.x
6.8.x
6.8.x
Slide 42
Rolling upgrade tests
7.4.x
6.8.x
6.8.x
Slide 43
Rolling upgrade tests
7.4.x
6.8.x
6.8.x
Slide 44
Rolling upgrade tests upgrade 7.4.x
7.4.x
6.8.x
Slide 45
Rolling upgrade tests
7.4.x
7.4.x
6.8.x
Slide 46
Rolling upgrade tests
7.4.x
7.4.x
6.8.x
Slide 47
Rolling upgrade tests upgrade 7.4.x
7.4.x
7.4.x
Slide 48
Rolling upgrade tests
7.4.x
7.4.x
7.4.x
Slide 49
Documentation Testing Y’all doing this, right?
Slide 50
Documentation Testing All documentation is written in asciidoc Fire up a test cluster Extract snippets from documentation Run snippets against cluster Optionally: check response contents
Embrace the difference Every product in the stack will test differently Java, JRuby, Ruby, Go, Javascript, TypeScript, Scala, .NET, perl, PHP, python, bash, Groovy, C++, Haskell, Clojure JSON, YAML, terraform, hcl
Slide 72
Everyone be ready! Releases are time based Every product’s branch should be ready Build of release candidate artifacts Testing of these artifacts Repeat until done across products: Fix all blockers Releasing of those artifacts
Slide 73
Release manager A person responsible for the release Triggers the build of all artifacts Performs follow up tasks for each team after a release
Slide 74
Trust the process! Staged artifacts are the final release artifacts, no rebuilds! Push artifacts to their final destinations Official links, OSS sonatype, rubygems, docker images, package repositories
Slide 75
Trust the process! +200 artifacts are promoted to release bucket Using Tekton Pipelines instead of single process started on release manager machine promoting artifacts: 4x faster 3rd party promotion: 6x faster > 40 pods are doing a single release
Slide 76
More Work begins after releasing website communication release blog posts ensuring everything has been published
Slide 77
Support it! Don’t forget to phase out…
Slide 78
Products have a lifecycle Stop supporting old products Be consistent with support guarantees Provide maintenance policy Distinguish between end of life & fixing bugs
Slide 79
Slide 80
Slide 81
Summary Automate all the things!
Slide 82
Summary Automate early, automate often Automate your tests, all of them Manual testing will still find bugs Automate your releases Ensure everyone can do a release Non-technical aspects are much harder to automate
Slide 83
Thanks for listening! Questions?
Alexander Reelsen @spinscale alex@elastic.co
Slide 84
Slide 85
Thanks for listening! Questions?
Alexander Reelsen @spinscale alex@elastic.co