DataStax: Making Cassandra Fail (for effective testing)

52
Making Cassandra fail for effective testing 1

Transcript of DataStax: Making Cassandra Fail (for effective testing)

Making Cassandra fail for effective testing1

chbatey

Who am IbullBased in LondonbullTechnical Evangelist for Apache CassandrabullWork on Stubbed CassandrabullHelp out Apache Cassandra users

bull Previous Cassandra backed apps at BSkyB

chbatey

Agendabull Realistic production environmentbull How does Cassandra fail- What should you dobull How to test your application

chbatey

Motivationbull Continuous integrationbull Continuous deployment

Commit code CI - tests Deploy to TestUAT

Deploy to realistic preprod

Production

bullSlower testsbullExploratory tests

chbatey

Production

Application

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Who am IbullBased in LondonbullTechnical Evangelist for Apache CassandrabullWork on Stubbed CassandrabullHelp out Apache Cassandra users

bull Previous Cassandra backed apps at BSkyB

chbatey

Agendabull Realistic production environmentbull How does Cassandra fail- What should you dobull How to test your application

chbatey

Motivationbull Continuous integrationbull Continuous deployment

Commit code CI - tests Deploy to TestUAT

Deploy to realistic preprod

Production

bullSlower testsbullExploratory tests

chbatey

Production

Application

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Agendabull Realistic production environmentbull How does Cassandra fail- What should you dobull How to test your application

chbatey

Motivationbull Continuous integrationbull Continuous deployment

Commit code CI - tests Deploy to TestUAT

Deploy to realistic preprod

Production

bullSlower testsbullExploratory tests

chbatey

Production

Application

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Motivationbull Continuous integrationbull Continuous deployment

Commit code CI - tests Deploy to TestUAT

Deploy to realistic preprod

Production

bullSlower testsbullExploratory tests

chbatey

Production

Application

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Production

Application

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

replication factor 3

consistency ONE

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Production

ApplicationApplicationApplicationApplicationApplication

ApplicationApplicationApplicationApplicationApplication

DC1

DC2

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Read timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Read timeout

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Read timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Data received

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Write timeout

Application C

R1

R2

R3C=QUROUM

Replication factor 3

timeout

timeout

Write timeout

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Retrying writesbull Cassandra does not roll back

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Write timeoutbull Received acknowledgementsbull Required acknowledgementsbull Consistency levelbull Batches are more complicated- WriteType SIMPLE BATCH UNLOGGED_BATCH

BATCH_LOG

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Batchesbull BATCH_LOG- Timed out waiting for batch log replicas- Retry if you likebull BATCH- Written to batch log but timed out waiting for actual replica- Will eventually be committed

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Idempotent writesbull All writes are idempotent with the following exceptions- Counters- lists

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Unavailable

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Unavailable

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Unavailablebull Alive Replicasbull Required Replicasbull Consistency

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

Application level timeout

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Unit amp Integration testingbull Requirements Quick to run deterministic not brittlebull Integration tests against an embedded Cassandra bull cassandra-unitbull Integration tests against an external Cassandra running on developer CI

machinesbull CCMbull Regular installbull Dockerbull Vagrant

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Acceptance testing

ApplicationAcceptance

test

prepare data

verification

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

How do this if it was a HTTP servicebull Wiremock - mocking HTTP

servicesbull Saboteur - adding network

latency

If you want to build a fault tolerant applicationyou better test faults

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

The optionsbull Disrupt traffic between driver and the clusterbull Disrupt traffic between Cassandra nodesbull Make Cassandra fail deterministically- Modify C code- Build a protocol level test double

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

The QueryHandler

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

KillrCassandra

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Stubbed Cassandra

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Native protocol

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Featuresbull Prime to respond to- Queries- Prepared statements- Batchesbull Simulate all failuresbull Disconnect clients

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Activity Client

bull Query Query text Consistency

bull PrepreparedStatementExecution Prepared statement text Bound variables

public ListltQuerygt retrieveQueries()

public ListltPreparedStatementExecutiongt retrievePreparedStatementExecutions()

public ListltConnectiongt retrieveConnections()

public void clearAllRecordedActivity()

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Priming Client

bull PrimingRequest Either a Query or PreparedStatement Query text or QueryPattern (regex) Consistency (default all) Result (success read timeout unavailable etc) Rows for successful response Column types for rows Variable types for prepared statements

public void prime(PrimingRequest prime) public ListltPrimingRequestgt retrievePreparedPrimes()public ListltPrimingRequestgt retrieveQueryPrimes()

public void clearAllPrimes()public void clearQueryPrimes()public void clearPreparedPrimes()

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Example timepublic interface PersonDao void connect() void disconnect() ListltPersongt retrievePeople() ListltPersongt retrievePeopleByName(String firstName) void storePerson(Person person)

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing the connect method given activityClientclearConnections()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect()

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing the connect method given activityClientclearConnections() when underTestconnect() then assertTrue(Expected at least one connection activityClientretrieveConnections()size() gt 0)

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing retrievepublic ListltPersongt retrieveNames() ResultSet result try Statement statement = new SimpleStatement(select from person) statementsetConsistencyLevel(ConsistencyLevelQUORUM) result = sessionexecute(statement) catch (ReadTimeoutException e) throw new UnableToRetrievePeopleException() ListltPersongt people = new ArrayListltgt() for (Row row result) peopleadd(new Person(rowgetString(first_name) rowgetInt(age))) return people

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople()

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Test the query + consistency given Query expectedQuery = Querybuilder() withQuery(select from person) withConsistency(QUORUM)build() when underTestretrievePeople() then assertThat(activityClientretrieveQueries() containsQuery(expectedQuery))

Hamcrest matcher

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople()

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing behaviour MapltString gt row = ImmutableMapof( first_name Chris last_name Batey age 29) primingClientprime(PrimingRequestqueryBuilder() withQuery(select from person) withColumnTypes(column(age PrimitiveTypeINT)) withRows(row) build()) when ListltPersongt names = underTestretrievePeople() then assertEquals(1 namessize()) assertEquals(ldquoChris Batey namesget(0)getName())

Each Cassandra Row == Java map

Tell Scassandra about your schema

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing errors given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout)

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing errorsTest(expected = UnableToRetrievePeopleExceptionclass) public void testHandlingOfReadRequestTimeout() throws Exception given PrimingRequest primeReadRequestTimeout = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(primeReadRequestTimeout) when underTestretrievePeople() then Expecting custom exception

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing retries Override public RetryDecision onReadTimeout(Statement statement ConsistencyLevel cl int requiredResponses int receivedResponses boolean dataRetrieved int nbRetry) if (nbRetry lt configuredRetries) return RetryDecisionretry(cl) else return RetryDecisionrethrow()

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e)

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing retries PrimingRequest readTimeoutPrime = PrimingRequestqueryBuilder() withQuery(select from person) withResult(Resultread_request_timeout) build() primingClientprime(readTimeoutPrime) try underTestretrievePeople() catch (UnableToRetrievePeopleException e) assertEquals(CONFIGURED_RETRIES + 1 activityClientretrieveQueries()size())

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Coordinator issue

Application C

R1

R2

R3C=QUROUM

Replication factor 3

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing slow connection given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime)

Delays the response by 1000ms

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Testing slow connectionTest(timeout = 500 expected = UnableToSavePersonExceptionclass) public void testThatSlowQueriesTimeout() throws Exception given PrimingRequest preparedStatementPrime = PrimingRequestpreparedStatementBuilder() withQueryPattern(insert into person) withVariableTypes(VARCHAR INT list(TIMESTAMP)) withFixedDelay(1000) build() primingClientprime(preparedStatementPrime) underTestconnect() underTeststorePerson(new Person(Christopher 29 CollectionsemptyList()))

Delays the response by 1000ms

Expect a custom exception

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Separate process

ApplicationAcceptance

test

prime on admin port (REST)

verification on admin port

Admin endpoints

Native protocol

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

How do I get itbull It is on maven central bullOr go to wwwscassandraorgbullExecutable jar + REST API

bull httpsgithubcomscassandrascassandra-server

ltdependencygt ltgroupIdgtorgscassandraltgroupIdgt ltartifactIdgtjava-clientltartifactIdgt ltversiongt091ltversiongt ltscopegttestltscopegt ltdependencygt

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

Summarybull Testing is good - I want more tools to help mebull Existing tools for Cassandra are great at happy path

scenariosbull Stubbed Cassandra allows testing of edge cases

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey

chbatey

The end - Questions

wwwscassandraorghttpchristopher-bateyblogspotcoukPing me on twitter chbatey