Skip to content

Commit

Permalink
📼 Record the test suite with VCR (#376)
Browse files Browse the repository at this point in the history
Changes the test setup to use VCR on any tests that hit the YouTube API.
Also simplifies the use of authentication credentials, and enables (or
deletes) all tests with the exception of those requiring authentication
on behalf of a content owner. Finally, changes `Request` and `Reports`
to make their retry times stubbable in order to speed up test runs.
  • Loading branch information
dgb committed Feb 14, 2020
1 parent bb8ec2d commit 3bb1c25
Show file tree
Hide file tree
Showing 223 changed files with 214,307 additions and 331 deletions.
5 changes: 1 addition & 4 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
--format documentation
--color
--tag ~rate_limited
--tag ~flaky
--tag ~extended_permissions
--exclude_pattern spec/requests/as_content_owner/*_spec.rb
--tag=~slow
54 changes: 22 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,44 +526,34 @@ If a variable is set in both places, then `Yt.configure` takes precedence.
How to test
===========

Yt comes with two different sets of tests:

1. tests in `spec/models`, `spec/collections` and `spec/errors` **do not hit** the YouTube API
1. tests in `spec/requests` **hit** the YouTube API and require authentication

To only run tests against models, collections and errors (which do not hit the API), type:
To run tests:

```bash
rspec spec/models spec/collections spec/errors
rspec
```

To also run live-tests against the YouTube API, type:
We recommend RSpec >= 3.8.

```bash
rspec
```
Yt comes with two different sets of tests:

1. Unit tests in `spec/models`, `spec/collections` and `spec/errors`
2. Legacy integration tests in `spec/requests`

Coming soon will be a new set of high-level integration tests.

Integration tests are recorded with VCR. Some of the tests refer to
fixture data that an arbitrary account may not have access to. If you
need to modify one of these tests or re-record the cassette, we'd
suggest working against your own version of the testing setup. Then in
your pull request, we can help canonize your test/fixtures.

Some of the integration tests require authentication. These can be set
with the following environment variables:

This will fail unless you have set up a test YouTube application and some
tests YouTube accounts (with appropriate fixture data) to hit the API.
Furthermore, tests that require authentication are divided into three
roles, which correspond to each directory in `spec/requests`:

* Account-based tests, which require a valid refresh token along with
the application-level credentials the refresh token was created with
(`YT_TEST_DEVICE_REFRESH_TOKEN`, `YT_TEST_DEVICE_CLIENT_ID`, and
`YT_TEST_DEVICE_CLIENT_SECRET` respectively).
* Server application tests, which use a server API key
(`YT_TEST_SERVER_API_KEY`).
* Tests that excercise YouTube's partner functionality. This requires an
a partner channel id (`YT_TEST_CONTENT_OWNER_NAME`), a refresh token
that's authenticated with that channel
(`YT_TEST_CONTENT_OWNER_REFRESH_TOKEN`), and the corresponding
application (`YT_TEST_PARTNER_CLIENT_ID` and
(`YT_TEST_PARTNER_CLIENT_SECRET`).

The refresh tokens need to be generated with the `youtube`,
`yt-analytics` and `userinfo.profile` permissions in order for tests to
pass.
* `YT_TEST_CLIENT_ID`
* `YT_TEST_CLIENT_SECRET`
* `YT_TEST_API_KEY`
* `YT_TEST_REFRESH_TOKEN`

How to release new versions
===========================
Expand Down
6 changes: 5 additions & 1 deletion lib/yt/collections/reports.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,15 @@ def within(days_range, country, state, dimension, videos, historical, max_retrie
# same query is a workaround that works and can hardly cause any damage.
# Similarly, once in while YouTube responds with a random 503 error.
rescue Yt::Error => e
(max_retries > 0) && rescue?(e) ? sleep(3) && within(days_range, country, state, dimension, videos, historical, max_retries - 1) : raise
(max_retries > 0) && rescue?(e) ? sleep(retry_time) && within(days_range, country, state, dimension, videos, historical, max_retries - 1) : raise
end

private

def retry_time
3
end

def type_cast(value, type)
case [type]
when [Integer] then value.to_i if value
Expand Down
6 changes: 5 additions & 1 deletion lib/yt/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,14 @@ def sleep_and_retry?(max_retries = 1)
@retries_so_far += 1
if (@retries_so_far < max_retries)
@response = @http_request = @uri = nil
sleep 3 + (10 * @retries_so_far)
sleep retry_time
end
end

def retry_time
3 + (10 * @retries_so_far)
end

# In case an authorized request responds with "Unauthorized", checks
# if the original access token can be refreshed. If that's the case,
# clears the memoized variables and returns true, so the request can
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3bb1c25

Please sign in to comment.