Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect custom OpenAPI spec file and start stripe-mock from test suite #715

Merged
merged 1 commit into from
Jan 11, 2019

Conversation

ob-stripe
Copy link
Contributor

@ob-stripe ob-stripe commented Dec 18, 2018

r? @brandur-stripe @remi-stripe

First attempt at embedding OpenAPI spec and fixtures files directly in the repo and using those for the test suite. Pretty rough, but it works.

Possible improvements:

  • better logs / error handling (done)
  • automatically choose an unused port (done)
  • detect "Listening for HTTP on port" in stripe-mock output instead of sleeping for 1 second

@ob-stripe
Copy link
Contributor Author

And of course the subprocess gem doesn't work with JRuby :(

@ob-stripe ob-stripe force-pushed the ob-openapi-files branch 2 times, most recently from bd28fe0 to 5ace43d Compare December 18, 2018 15:28
@ob-stripe
Copy link
Contributor Author

Alright, went for a slightly different approach.

The test suite now checks if STRIPE_MOCK_PORT is set. If it is, it assumes that stripe-mock is already running and uses that port, otherwise (if not running on JRuby) it attempts to start its own stripe-mock process on a random unused port itself (and kills it once it's done).

The idea is that on CI, we'd manually start stripe-mock and set STRIPE_MOCK_PORT and on our development machines we can simply run the test suite and it will spawn the process itself.

Let me know what you think! If you think this is a good approach, I'll update the README file accordingly.

.travis.yml Outdated
-http-port ${STRIPE_MOCK_PORT} \
-spec test/openapi/spec3.json \
-fixtures test/openapi/fixtures3.json \
> /dev/null &
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wanted to make sure, but I assume that this is an artifact of an older attempt? It seems to be running basically the same thing as Stripe::StripeMock.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I saw your note about running differently in CI. Still not sure I 100% understand the expected workflow here, but I'll leave that in a comment below.

@brandur-stripe
Copy link
Contributor

@ob-stripe Thanks for taking a stab here! Sorry about the super late reply :/

First of all: I just want to get a general idea of the suggested workflow here. Is the idea that test/stripe_mock.rb would come into master, but most of these pieces like changes to .travis.yml and test/openapi/ would only be present on development branches where they're needed?

If so, I wonder if we should just have a single override flag somewhere for use in CI that boots an automatic stripe-mock (like you get locally), but requires minimal changes to .travis.yml or anything else just to make the workflow as easy as possible.

And sorry, but just a couple other points of FUD for completeness:

  1. If we can avoid it, I'd prefer not to bring any OpenAPI specs into the master tree because they'll bloat the repository quite a bit. The spec is ~1.5 MB while all other files in the repo combined are ~1 MB.
  2. IMO if we go this route, we should avoid the use of the subprocess gem, and prefer just the use of the standard library's subprocess-handling mechanics, which are more than sufficient. As far as I can tell, subprocess is a Stripe NIH project that was probably developed originally due to insufficient understanding of built-in mechanics (see issue logged here years ago). It's not maintained, and not worth the new dependency.

@ob-stripe ob-stripe force-pushed the ob-openapi-files branch 6 times, most recently from 859f6bf to 586d503 Compare January 4, 2019 11:30
@ob-stripe
Copy link
Contributor Author

Is the idea that test/stripe_mock.rb would come into master, but most of these pieces like changes to .travis.yml and test/openapi/ would only be present on development branches where they're needed?

I don't feel super strongly about it but I'd personally lean towards having everything in master, for consistency and to make it easier to deal with multiple betas in parallel. It would also make it easier to identify the exact surface of a specific beta, by looking at the diff for the spec.

If we can avoid it, I'd prefer not to bring any OpenAPI specs into the master tree because they'll bloat the repository quite a bit. The spec is ~1.5 MB while all other files in the repo combined are ~1 MB.

Good point. I just copied the raw files for simplicity's sake, but we could also use a git submodule like in stripe-mock.

IMO if we go this route, we should avoid the use of the subprocess gem, and prefer just the use of the standard library's subprocess-handling mechanics, which are more than sufficient. As far as I can tell, subprocess is a Stripe NIH project that was probably developed originally due to insufficient understanding of built-in mechanics (see issue logged here years ago). It's not maintained, and not worth the new dependency.

👍 I've updated the PR to remove the dependency on subprocess and use ::Process.spawn instead. The good news is that this works with JRuby, so it's no longer necessary to start stripe-mock externally even in CI. I've updated .travis.yml to simply unpack stripe-mock and add it to PATH.

@brandur-stripe
Copy link
Contributor

I don't feel super strongly about it but I'd personally lean towards having everything in master, for consistency and to make it easier to deal with multiple betas in parallel. It would also make it easier to identify the exact surface of a specific beta, by looking at the diff for the spec.

Oh I see. So the current (non-alpha/beta/etc.) OpenAPI spec is in master, and branches where alphas/betas/etc are implemented just overwrite that spec right?

Good point. I just copied the raw files for simplicity's sake, but we could also use a git submodule like in stripe-mock.

K cool. Not saying we should do that for sure because as discussed before, submodules are a pain, but I'm a little afraid that we eventually go through enough iterations on the spec that we end up accidentally making the repo pretty heavyweight.

👍 I've updated the PR to remove the dependency on subprocess and use ::Process.spawn instead. The good news is that this works with JRuby, so it's no longer necessary to start stripe-mock externally even in CI. I've updated .travis.yml to simply unpack stripe-mock and add it to PATH.

Awesome! This is wayyyy better.

Just reading this over, it looks to me that when running the test suite locally, a new version of stripe-mock is always started, even on the master branch (unless you have STRIPE_MOCK_PORT set in your environment, but I don't think most people do). Was that intentional? It seems like we should try to have it favor the already-running stripe-mock where possible for speed if nothing else.

@ob-stripe
Copy link
Contributor Author

Oh I see. So the current (non-alpha/beta/etc.) OpenAPI spec is in master, and branches where alphas/betas/etc are implemented just overwrite that spec right?

Yeah exactly. This way you'd have all the information in one place when looking at the diff between the beta branch and master. Not required by any means, but I thought it'd be nice.

Just reading this over, it looks to me that when running the test suite locally, a new version of stripe-mock is always started, even on the master branch (unless you have STRIPE_MOCK_PORT set in your environment, but I don't think most people do). Was that intentional? It seems like we should try to have it favor the already-running stripe-mock where possible for speed if nothing else.

We've often run into issues where some tests would fail after upgrading your local instance of stripe-mock (e.g. after running brew update && brew upgrade if you installed via brew), so I kind of like the idea of the test suite always running its own stripe-mock instance with the correct spec and fixtures files.

If we don't do this though, how would you recommend checking for master vs. beta branch? We could either just have different code in the beta branches, or do something like git rev-parse --symbolic-full-name --abbrev-ref HEAD to check if the current branch is master (but then you'd have to run the test suite from the git repo).

@brandur-stripe
Copy link
Contributor

Yeah exactly. This way you'd have all the information in one place when looking at the diff between the beta branch and master. Not required by any means, but I thought it'd be nice.

Yep, makes sense.

We've often run into issues where some tests would fail after upgrading your local instance of stripe-mock (e.g. after running brew update && brew upgrade if you installed via brew), so I kind of like the idea of the test suite always running its own stripe-mock instance with the correct spec and fixtures files.

Those failures are generally well-documented at least right? As in, the test suite fails with "the minimum stripe-mock needed is X.X.X". (I'm not sure if there's some other type of "upgrade failure" that I can't think of.)

I sort of like the idea of continuing to fall back to the system's stripe-mock as much as possible just to keep things really, really fast. The test suites for languages like Ruby and Go are fast enough now that launching a new process every time would be a noticeable slow down. There also may be that problem of Mac OS popping up the "stripe-mock allow like to listen on port XXX, allow/deny" dialog all the time which would be pretty annoying.

If we don't do this though, how would you recommend checking for master vs. beta branch? We could either just have different code in the beta branches, or do something like git rev-parse --symbolic-full-name --abbrev-ref HEAD to check if the current branch is master (but then you'd have to run the test suite from the git repo).

Hm, a Git-based solution seems relatively plausible — I'd probably suggest a chance to your approach a bit by checking whether the current branch has any modifications in the directory containing the OpenAPI specs. That way non-beta branches on both your local machine and in CI could continue to use system stripe-mock.

I also think that it might not be that bad to make the launch explicit on beta branches. As in we add a line that's normally commented out like:

# Uncomment for an alpha/beta branch that need stripe-mock to use custom OpenAPI.
# Stripe::StripeMock.start

Admittedly though, there'd always be risk of it being accidentally merged to master.

@ob-stripe ob-stripe force-pushed the ob-openapi-files branch 2 times, most recently from 802de09 to 722c9cb Compare January 10, 2019 14:05
@ob-stripe
Copy link
Contributor Author

Okay, I've updated the PR with your feedback. Now the test suite looks for a spec3.json file in test/openapi/. If it exists, then the suite will start its own stripe-mock process with the custom spec file, otherwise it assumes that stripe-mock is already running.

This way, we can merge this PR into master and keep the existing behavior. In beta branches, all we need to do is include the custom spec3.json and fixtures3.json files in test/openapi/ and the test suite will start stripe-mock with those custom files instead of using the already running stripe-mock process.

ptal @brandur-stripe

@brandur-stripe
Copy link
Contributor

Nice! LGTM.

I'm really liking not having the spec bundled in master and falling back on the system's stripe-mock by default. Hopefully I didn't end up pushing us in a direction that will overall be harder to use, but if I did, feel free to push back by iterating on the design in the future once we know more from having started to use it.

@ob-stripe ob-stripe changed the title [wip] Embed OpenAPI files and start stripe-mock from test suite Detect custom OpenAPI spec file and start stripe-mock from test suite Jan 11, 2019
@ob-stripe
Copy link
Contributor Author

Alright, thanks @brandur-stripe! Pulling this in.

@ob-stripe ob-stripe merged commit 7f55cf3 into master Jan 11, 2019
@ob-stripe ob-stripe deleted the ob-openapi-files branch January 11, 2019 11:08
@ob-stripe ob-stripe restored the ob-openapi-files branch January 11, 2019 11:08
@ob-stripe ob-stripe deleted the ob-openapi-files branch January 11, 2019 11:08
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
brandur-stripe pushed a commit to stripe/stripe-go that referenced this pull request Jan 22, 2019
Very similar to the recent feature implemented in other languages (for
example [1]), this wraps test runs in a script which will detect a
custom OpenAPI spec and fixture in `testing/openapi/` and start a local
version of stripe-mock pointing to them. The test suite is then executed
against that stripe-mock and it's shut down afterwards.

If there isn't a custom OpenAPI spec, we continue to fall back to the
system stripe-mock to keep test runs as fast as possible.

This differs a little from implementations in other languages in that we
had to start stripe-mock from a script (as opposed to a `before` block
or the like) because Go's testing tools don't give us a place where we
can do anything before any test runs. Therefore, we start stripe-mock
then execute `go test ./...` as a subprocess.

[1] stripe/stripe-ruby#715
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants