Add offline entitlements integration tests#1006
Conversation
There was a problem hiding this comment.
I moved some logic from PurchasesIntegrationTest to this base class.
There was a problem hiding this comment.
This was added because onActivityReady wasn't guaranteed to be executed in order which resulted in some flaky tests. This way, we execute the test setup code and the test itself within a single onActivityReady.
There was a problem hiding this comment.
Copied this from the BackendIntegrationTest which are actually unit tests unlike this.
There was a problem hiding this comment.
Ideally we should also migrate these tests to use a single onActivityReady. But will do that in a different PR.
There was a problem hiding this comment.
It's not great to duplicate these cache keys... But I didn't want to expose them in the common module just for this... I think it's ok? Lmk what you think
There was a problem hiding this comment.
Creating these fake products is a bit hacky... We could create them from mocked google product details but that also doesn't feel great to me though, I think this is relatively simpler. Note that this is needed whether we use a proxy or not since we can't get the product info from Google directly.
|
Still want to write some more tests including:
|
Codecov Report
@@ Coverage Diff @@
## main #1006 +/- ##
==========================================
- Coverage 85.40% 85.37% -0.04%
==========================================
Files 169 169
Lines 5997 6002 +5
Branches 836 839 +3
==========================================
+ Hits 5122 5124 +2
- Misses 544 545 +1
- Partials 331 333 +2
|
tonidero
left a comment
There was a problem hiding this comment.
This is still WIP but I would like some feedback on the approach @RevenueCat/coresdk .
I think this is much simpler than having to run a separate process for the proxy and enable/disable different endpoints in the middle of the test. On the other hand, I agree that hardcoding the success responses makes it much more brittle. I believe that it's somewhat acceptable to hardcode the responses, since we are hitting the backend in other integration tests. We can still use the proxy for manual testing though. Lmk what you think!
There was a problem hiding this comment.
Added these to be able to mock the initial state of shared preferences and active purchases within the integration test.
c6f739b to
8d526d4
Compare
ee9953f to
fcadf07
Compare
tonidero
left a comment
There was a problem hiding this comment.
These tests don't look nearly as nice in Android as they do in iOS. One of the main differences is coroutine support. That would make the tests much more legible. I tried to avoid as many callbacks as possible but still not nearly as nice. I guess another reason to consider supporting coroutines soon
There was a problem hiding this comment.
Added a completion here to be able to wait upon it on tests. It won't be used in production. Still it's tested.
There was a problem hiding this comment.
As an improvement you could forward the error too so integration tests can ensure it actually worked?
There was a problem hiding this comment.
Had to increase the timeout... Honestly this is already large, but in Android we do all requests sequentially and that's taking a long time for the new tests. Also, randomly the tests will take twice as long... We will probably want to improve the performance of the integration tests soon, but for now I wanted to get them running first. Also, the fact that we are using callbacks and not coroutines makes it necessary for us to put a timeout for the whole test :(
There was a problem hiding this comment.
iOS integration tests are also not the fastest because we need to wait on purchase expirations. I think it's okay that these tests aren't the fastest, as long as unit tests are.
|
This is ready for review @RevenueCat/coresdk |
There was a problem hiding this comment.
Note that I didn't add automated tests that tested offline entitlements with multiple purchases. Reasons being:
- I would need to assume many things about how Google works in order to mock it realistically. I really wish Google released something to test purchases more easily :(.
- We would need another valid token for a different product if we wanted to test it against the backend
There was a problem hiding this comment.
I wanted to note that this only works for these tests that are using offline entitlements. The token we currently are using for integration tests is for a expired purchase, that means that the backend won't return it as an active purchase. For these tests I'm mocking the purchase as returned from the Google method "queryPurchases" which returns active purchases, that's why it ends up as an active purchase there.
That's also the reason why I'm not verifying that the purchases are active after recovering from offline entitlements mode and only verifying that the purchase is acknowledged and sent to the backend.
This is not really great. I think we can improve this a lot by having an active purchase forever in a company credit card. Will study this option and try to improve this a bit.
NachoSoto
left a comment
There was a problem hiding this comment.
This is a great start 👍🏻
There was a problem hiding this comment.
As an improvement you could forward the error too so integration tests can ensure it actually worked?
There was a problem hiding this comment.
iOS integration tests are also not the fastest because we need to wait on purchase expirations. I think it's okay that these tests aren't the fastest, as long as unit tests are.
There was a problem hiding this comment.
Is it a problem that this is in this order? The code waiting for the latch would be notified before you fail the test.
There was a problem hiding this comment.
Right, I think we should completely remove the countdown in these error cases, I added it on an early iteration but it's not really needed, and can cause errors as you said. Good catch!
There was a problem hiding this comment.
Maybe verify the error is a server error and not something else?
There was a problem hiding this comment.
Ditto order and in the other tests.
There was a problem hiding this comment.
This is a noun, so postSetup makes sense 😅
|
Thanks for the suggestions @NachoSoto! Refactored the integration tests pretty heavily into different classes. So will need another review 🙏 |
10ed485 to
f2b61ce
Compare
91a1706 to
f2b61ce
Compare
f2b61ce to
f59ea0d
Compare
### Description After adding the integration tests for offline entitlements in #1006, I was testing running each set of tests separately. However, I was changing the parameters we use to run integration tests between normal integration tests and the offline entitlement tests in order to make them pass. In order to make them compatible, I'm just hardcoding the entitlements we verify are granted after purchases during offline entitlements integration tests.
**This is an automatic release.** ### New Features * Support DEFERRED mode (#985) via swehner (@swehner) * Add completion callback to syncPurchases API (#1002) via Toni Rico (@tonidero) ### Bugfixes * Workaround bug in android 4 for JSON objects with List<String> (#942) via Andy Boedo (@aboedo) ### Dependency Updates * Bump fastlane-plugin-revenuecat_internal from `fe45299` to `13773d2` (#1015) via dependabot[bot] (@dependabot[bot]) ### Other Changes * Bump dokka to 1.8.10 to support Gradle 8 (#1009) via Toni Rico (@tonidero) * Disable offline entitlements temporarily (#1023) via Toni Rico (@tonidero) * Fix integration tests in CI (#1019) via Toni Rico (@tonidero) * Add offline entitlements integration tests (#1006) via Toni Rico (@tonidero) * Disable offline entitlements in observer mode (#1014) via Toni Rico (@tonidero) * Extracts setup and teardown to BasePurchasesTest (#1011) via Cesar de la Vega (@vegaro) * Support forcing server errors for tests (#1008) via Toni Rico (@tonidero) --------- Co-authored-by: revenuecat-ops <ops@revenuecat.com> Co-authored-by: Toni Rico <antonio.rico.diez@revenuecat.com>
Description
Depends on #987
This PR adds some integration tests checking some basic behaviors of offline entitlements. Mostly making sure the mode is turn on and off as expected.