Support sequential read/write tape modes #70

Closed
wants to merge 6 commits into
from

Conversation

Projects
None yet
3 participants
@steveims

Rob, thanks for betamax! We've been using it to enable component testing. Along the way, we've found that one of our preferred usage patterns relies upon a sequence of HTTP interactions. For example, one of our common scenarios is business logic that manipulates a data object. Part of that logic includes simple interactions to a backend system, such as:

  1. GET /resource
  2. modify the entity, then PUT /resource
  3. GET /resource

betamax doesn't distinguish interactions 1 and 3, so we added sequential read/write tape modes:
WRITE_SEQUENTIAL records each HTTP interaction in order.
READ_SEQUENTIAL replays the HTTP interactions in order; if the HTTP request doesn't match the next recorded request, then we throw an IllegalStateException. Thus READ_SEQUENTIAL asserts that each request matches the recorded request.

This pull request contains themodifications to support sequential read/write tape modes. I offer this for your consideration as a new feature for betamax.

Thanks again for this project!

-- Steve

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Oct 18, 2012

Collaborator

Wow, that looks great. There's been an issue for implementing this for a while (#7) but I haven't got round to even looking at it.

I'm going to add some test coverage around this & roll it into a release. For the time being I have released version 1.2-SNAPSHOT on http://oss.sonatype.org/content/groups/public/ with your changes.

Thanks again for a really useful feature.

Collaborator

robfletcher commented Oct 18, 2012

Wow, that looks great. There's been an issue for implementing this for a while (#7) but I haven't got round to even looking at it.

I'm going to add some test coverage around this & roll it into a release. For the time being I have released version 1.2-SNAPSHOT on http://oss.sonatype.org/content/groups/public/ with your changes.

Thanks again for a really useful feature.

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Oct 21, 2012

Collaborator

@steveims can I ask if there's a reason you didn't support 'looping', i.e. that in READ_SEQUENTIAL mode the sequence gets repeated if more requests are made than there are recordings? Would that be a problem for you if I added it? It's kind of an edge case as one would expect the same number of requests to happen but right now an ArrayIndexOutOfBoundsException is thrown & I'd like to handle things in a cleaner way.

Collaborator

robfletcher commented Oct 21, 2012

@steveims can I ask if there's a reason you didn't support 'looping', i.e. that in READ_SEQUENTIAL mode the sequence gets repeated if more requests are made than there are recordings? Would that be a problem for you if I added it? It's kind of an edge case as one would expect the same number of requests to happen but right now an ArrayIndexOutOfBoundsException is thrown & I'd like to handle things in a cleaner way.

@steveims

This comment has been minimized.

Show comment Hide comment
@steveims

steveims Oct 21, 2012

@robfletcher Depends how you want to interpret "sequential mode." We built it as a means to manage very controlled tests. Sequential reads enable us to build unit tests to confirm our HTTP interactions. That includes confirming that the request matches the expected (asserted within Betamax); our client code receives the corresponding response and our unit code asserts our handling of that response.

So controlled order and number of records is important. Reading after end of tape (in sequential mode) means the flow has changed, so we expect an error. Likely a new tape needs to be recorded.

I'm not sure of the use case for looping? Concurrent requests sounds non-deterministic, which seems outside the scope of a sequential tape?

@robfletcher Depends how you want to interpret "sequential mode." We built it as a means to manage very controlled tests. Sequential reads enable us to build unit tests to confirm our HTTP interactions. That includes confirming that the request matches the expected (asserted within Betamax); our client code receives the corresponding response and our unit code asserts our handling of that response.

So controlled order and number of records is important. Reading after end of tape (in sequential mode) means the flow has changed, so we expect an error. Likely a new tape needs to be recorded.

I'm not sure of the use case for looping? Concurrent requests sounds non-deterministic, which seems outside the scope of a sequential tape?

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Oct 22, 2012

Collaborator

I guess the problem is there are 3 different ways to approach this:

  • don't loop, return an error if more requests are made than exist on tape
  • loop round if more requests are made
  • continue returning the last matching request if more requests are made (like Spock mocks)

These would all make sense in different scenarios. That said Betamax should probably keep it simple. If someone needs to integration test against a REST endpoint they should do so. I think I'll go with what you originally committed and just ensure a reasonable error is returned to the client.

Collaborator

robfletcher commented Oct 22, 2012

I guess the problem is there are 3 different ways to approach this:

  • don't loop, return an error if more requests are made than exist on tape
  • loop round if more requests are made
  • continue returning the last matching request if more requests are made (like Spock mocks)

These would all make sense in different scenarios. That said Betamax should probably keep it simple. If someone needs to integration test against a REST endpoint they should do so. I think I'll go with what you originally committed and just ensure a reasonable error is returned to the client.

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Oct 22, 2012

Collaborator

I'm going to merge this into master.

There is a small thread safety issue where you might get a HTTP 500 instead of a 403 if you send too many requests or out of sequence requests to a sequential tape using multiple threads. If all the requests on the tape match and you don't send too many requests it is thread safe and guarantees that no two threads will get sent the same recorded response.

I want to rethink the HTTP status codes anyway so I'll roll handling that problem into #71.

@steveims I've updated 1.2-SNAPSHOT with the final version of this code. Let me know if you see any issues.

Collaborator

robfletcher commented Oct 22, 2012

I'm going to merge this into master.

There is a small thread safety issue where you might get a HTTP 500 instead of a 403 if you send too many requests or out of sequence requests to a sequential tape using multiple threads. If all the requests on the tape match and you don't send too many requests it is thread safe and guarantees that no two threads will get sent the same recorded response.

I want to rethink the HTTP status codes anyway so I'll roll handling that problem into #71.

@steveims I've updated 1.2-SNAPSHOT with the final version of this code. Let me know if you see any issues.

@steveims

This comment has been minimized.

Show comment Hide comment
@steveims

steveims Oct 22, 2012

@robfletcher Looks good. Thanks!

@robfletcher Looks good. Thanks!

@EwaKowalczuk

This comment has been minimized.

Show comment Hide comment
@EwaKowalczuk

EwaKowalczuk Feb 26, 2014

Hi, as this issue is closed, I would like to ask if the modes are now integrated into the code that you can download on your site? I can see them in the documentation, on your main page, but not in downloaded code (1.1.2). Thanks!

Hi, as this issue is closed, I would like to ask if the modes are now integrated into the code that you can download on your site? I can see them in the documentation, on your main page, but not in downloaded code (1.1.2). Thanks!

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Feb 26, 2014

Collaborator

It's in 2.0-SNAPSHOT which is available from oss.jfrog.org.

Collaborator

robfletcher commented Feb 26, 2014

It's in 2.0-SNAPSHOT which is available from oss.jfrog.org.

@EwaKowalczuk

This comment has been minimized.

Show comment Hide comment
@EwaKowalczuk

EwaKowalczuk Feb 27, 2014

Thanks for the quick response :)

Thanks for the quick response :)

@robfletcher

This comment has been minimized.

Show comment Hide comment
@robfletcher

robfletcher Feb 27, 2014

Collaborator

No problem. Let me know how it's working for you. There are some differences between 1.2 and 2.0 and I'm still ironing out a number of compatibility issues with various frameworks – Grails in particular but I don't anticipate any further major API changes before 2.0

Collaborator

robfletcher commented Feb 27, 2014

No problem. Let me know how it's working for you. There are some differences between 1.2 and 2.0 and I'm still ironing out a number of compatibility issues with various frameworks – Grails in particular but I don't anticipate any further major API changes before 2.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment