Post on 10-Feb-2017
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