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

Override Test ID to ensure trait dependencies are cached #293

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jflan-dd
Copy link

@jflan-dd jflan-dd commented Oct 16, 2024

I ran into an issue where reference typed dependencies weren't correctly cached if they were updated in-place rather than being fully overridden.

The root cause of this seems to be that Test.current isn't set during prepare(for test: Test) and as a result the CacheKey.testIdentifier was nil during dependency setup.

This PR creates an internal TestID struct that can be explicitly overridden during dependency prep, but perhaps there's a more elegant solution that could be implemented in xctest-dymaic-overlay directly.

This PR is dependent on pointfreeco/swift-issue-reporting#137

@jflan-dd
Copy link
Author

jflan-dd commented Oct 16, 2024

It seems like this could also be solved with a TestExecuting conformance if https://forums.swift.org/t/pitch-custom-test-execution-traits/75055/14 lands, since Test.current is set before _executeTraits is called

Is there a plan for how to be backwards compatible with different versions of swift-testing as new features are added?

@stephencelis
Copy link
Member

@jflan-dd Thanks for looking into this and putting together a PR! We'll try to review it soon.

@jflan-dd
Copy link
Author

@stephencelis I created a separate PR in swift-issue-reporting to support overriding the TestContext which greatly simplified this PR

@stephencelis
Copy link
Member

@jflan-dd This hasn't fallen off our radar but we haven't had time to fully review and grok things yet. Hopefully soon!

@jflan-dd
Copy link
Author

jflan-dd commented Nov 11, 2024

@stephencelis no problem. We're working around this issue by explicitly setting the mock dependency inside of the update block so that the DependencyValues setter is called directly, although I haven't tested our workaround with this change yet.

For additional context my understanding of the issue is that because swift-testing doesn't set the test ID before prepare(for:) it's causing this cache key to have a nil testIdentifier when updating dependencies inside of the updateValues closure. This isn't an issue for dependencies with value semantic because they end up in this else case which stores the updated dependency directly in the DependencyValues storage rather than using the cache.

This results in caching the updated dependency with an invalid cache key, which causes a cache miss when the dependency is accessed during the test.

This image shows a breakpoint while accessing the dependency within the body of a test. The cache contains a dependency with the same TypeIdentifier from the trait update, but there's a cache miss because the testIdentifiers don't match.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants