-
Notifications
You must be signed in to change notification settings - Fork 30
Add test extension [ECR-2634] #582
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
I would make this extension create things on demand (i.e., create a snapshot or fork only if it is needed).
-
I doubt that it will work correctly with parallel tests, as it uses its fields to store per-test data. As extensions are usually instantiated once, it is not recommended: https://junit.org/junit5/docs/current/user-guide/#extensions-keeping-state and http://blog.codefx.org/design/architecture/junit-5-extension-model/#Stateless
It seems that you can use a CloseableResource
in a Store
to be notified when the context has finished: https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/extension/ExtensionContext.html#getStore(org.junit.jupiter.api.extension.ExtensionContext.Namespace)
As the store is hierarchical, I guess the following will also work with the store (but please confirm in the docs and test):
- A MemoryDb is injected in
@BeforeEach
; the setup method writes some stuff into a fork and merges it into the database. - A
Snapshot
is injected in@Test
; theMemoryDb
is queried from the store under the hood, hence the snapshot contains the stuff written in@BeforeEach
.
You may also see https://github.com/junit-pioneer/junit-pioneer/blob/master/src/main/java/org/junitpioneer/jupiter/TempDirectory.java extension as an example.
It seems after @dmitry-timofeev comments that this extensions adds more headache than actual benefits. Can we keep it simple at least in tests ? |
@DENMROOT at the moment we have 59 @dmitry-timofeev should we also move
to this extension? That'd reduce boilerplate code in tests that use views |
It is a good idea, if the library is available at extension instantiation time. Regarding the possible complexity, we can't estimate it until we see. As this is a spike, the goal here is to explore this solution and then decide if it makes sense to use it. It seems that the extension model has some nice built-in things (like a hierarchical store with built-in lifecycle management of stored objects) that might possibly make the implementation quite consice.
On top of reducing repetition and noise in our tests, this extension might be an early prototype of Java Binding Testkit, i.e., an extension that we will distribute to end-users to make testing of services easier. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good, thanks. There are a couple of questions/improvements, but I think they can be resolved during implementation. Please put them in a ticket so that we can get back to them.
static { | ||
LibraryLoader.load(); | ||
@BeforeEach | ||
void setUp(MemoryDb db) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's just for illustrative purposes, i.e., it's not needed for the below test to work, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's not needed, just a demonstration that we can inject parameters into @BeforeEach
as well
} | ||
|
||
private Store getStore(ExtensionContext context) { | ||
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this code use just a single constant namespace, because the store is hierarchical:
- FooTest
- setUp(MemoryDb) <- If we resolve MemoryDb here to instance A,
- test1(MemoryDb) <- … the same instance A will be accessible here
- test2(Snapshot) <- … and this snapshot must come from the same instance A too
- BarTest
- test3(MemoryDb, Fork) <- Has a distinct store from FooTest, hence will create a new MemoryDb instance B and get a fork from it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could do it either way
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod())); | ||
} | ||
|
||
private static class CloseableDbAndCleaner implements CloseableResource { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably makes sense to bind a Fork/Snapshot to a Cleaner, not a database.
return memoryDb; | ||
} | ||
else { | ||
Cleaner cleaner = resources.getCleaner(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can probably simplify things too (with hierarchical store), as before each callback will no longer be needed:
MemoryDb memoryDb = store.getOrComputeIfAbsent(MEMORY_DB_KEY, CloseableMemoryDb::new);
if (requestedType == MemoryDb.class) {
return memoryDb;
}
// …
It seems natural to allow to inject the same memoryDb as in setup method (which merges some data), but shall we also allow reusing snapshots and forks in lower levels of the lifecycle hierarchy? If we do not, which seems like a reasonable behaviour, then how do we destroy a cleaner exactly after the setUp?
Closing, as I don't think this is needed after TestKit extension implementation - #913. |
Overview
Use Extension to get rid of repetitive views instantiation.
See: https://jira.bf.local/browse/ECR-2634
Definition of Done