See #86 for background
@rnorth I can take TestNG support since one of our projects is using it :) See #132
Cool, thanks! In terms of structuring this, I think there's a reasonably chunky refactoring coming up in the future so it might be best to consider now. I'm thinking that:
containercore) that is completely test framework agnostic. _Part of the rationale also includes potentially using the library in non-test contexts, BTW, which is admittedly a bit of a revision on my previous ROADMAP thinking ;)_This diagram roughly illustrates my thinking (please excuse the UML ;)):
What do you think?
@rnorth looks good! I'm thinking about some refactorings before we start (especially in case of v2.0.0), will write them down to discuss a little bit later
I'd be very interested in a version of which does not include any JUnit dependencies. I'm currently developing a Docker extension for Spock (https://github.com/kiview/spock-docker-extension) and I'm using the Groovy Docker Client (https://github.com/gesellix/docker-client).
Lot's of the feature I still need add to my extension are already available in testcontainers in a quite accessible and convenient manner. So I wonder how I could best integrate testconainters into my project, or help in modularising the current version of the library. As for the time being I'm still hesistant in integrating this project as long as this will include JUnit dependencies.
@kiview thanks for the comment - sorry for the delay in responding!
Yes, breaking the JUnit dependency is absolutely something I'd like to do, as you can see from this ticket.
It would probably be reasonable to do #240 at the same time; either as a separate JAR for DockerClientFactory, or make it a consciously public (exposed) member of the containercore lib. Personally I feel the latter would be reasonable. What do you think @bsideup?
@rnorth sounds good for me. I have some free time this week, so I can take this task if you don't mind :) I see two tasks here - one for "JUnit-free core" and another one "separate DockerClientFactory", so we can split the work. WDYT?
@bsideup sure, that'd be great! Does the diagram above make sense, or do you want to discuss any refinements?
DockerClientFactory would probably have to move into the new containercore JAR anyway, but yeah I'd imagine the tidy-up work to make DCF be a real reusable class can follow.
@rnorth it looks good, but I can't say exactly until I start :)
Also, looks like there is only one open external PR, so I think it's a good time to start 2.x
I'll try to explain my use cases when using this library in conjunction with the spock extension:
Bonus points for Windows support with named pipes ;)
Another thing which would be awesome would be the possibility to run my tests inside a container, so I can use features like docker networking to access my testcontainers. But this seems like another project ;) (Gradle plugin maybe?)
I'll be a bit easier to satisfy :p
I started working on JUnit5 extensions because it allows the user to choose in which order the executions will be executed (the order of the declaration).
My goal is very simple : have a convenient way to manage containers as an extension. A use case example is to start a database container before starting an ORM framework like hibernate or Spring data.
To do so, my current code just needs to be able to create a adapter with this simple interface : https://github.com/FaustXVI/junit5-docker/blob/master/src/main/java/com/github/junit5docker/DockerClientAdapter.java
Maybe this interface could be a starting point ? @kiview would it fits your needs (for now) ?
My currently used interface hast indeed quite similar methods:
https://github.com/kiview/spock-docker-extension/blob/master/src/main/groovy/com/groovycoder/spockdockerextension/DockerClientFacade.groovy
I even think about keeping this facade class and simply substitute the used docker library with testcontainers, since testcontainers already gives mehr a high level of abstraction. This would mean, I would use testcontainers as a high level Docker client.
@rnorth @FaustXVI is pure JUnit5 support (without vintage engine) support on the roadmap? @Rule and @ClassRule are going away... is this likely to be a difficult problem to solve. Thanks!
Today I pushed an experiment with JUnit 5 to the branch:
https://github.com/testcontainers/testcontainers-java/tree/junit5/modules/junit5
Feedback is welcome :)
AFAICT there's no reason the containers need to extend TestRule directly. Instead, it seems it'd be fairly trivial to have the containers completely isolated from JUnit, with manual start/stop abilities (and potentially a Runtime hook to cleanup on shutdown. Then, it would be trivial to create integrations that could tie the engine into JUnit 4/5.
I'm probably doing things a bit different than others, but personally I'm creating containers for postgres/rabbitmq during test instantiation, which is then shared between multiple tests (even with TestContainers, the overhead of restarting containers on every test run is too high). So, I'm not using any of the JUnit integration. That said, I still have to have JUnit 4 on the classpath to be able to use it (because it extends TestRule).
@colinmorelli yes, TestRule was there for historical reasons. Check my previous comment where I linked to JUnit 5 branch. We cannot just remove extends TestRule until we're ready to break the binary compatibility, but TC 2.0 will have it removed.
P.S. personally, I use TC a lot, but I also start them with static blocks and not using the rules:
https://github.com/bsideup/testcontainers-microservices-example/blob/5d28ca32d29d9fd7f3101044a02ec2660b0678fd/src/test/java/org/testcontainers/example/demo/support/AbstractIntegrationTest.java#L38
@bsideup when do you think TC2.0 will be releases? Has it already started?
P.S. personally, I use TC a lot, but I also start them with static blocks and not using the rules:
https://github.com/bsideup/testcontainers-microservices-example/blob/5d28ca32d29d9fd7f3101044a02ec2660b0678fd/src/test/java/org/testcontainers/example/demo/support/AbstractIntegrationTest.java#L38
@bsideup Nice solution, but what about stopping. Why you are not stopping the containers?
Testcontainers will stop it for you automatically after the tests :)
On Thu, 17 May 2018 at 13:30, Aleksandr Podkutin notifications@github.com
wrote:
P.S. personally, I use TC a lot, but I also start them with static blocks
and not using the rules:@bsideup https://github.com/bsideup Nice solution, but what about
stopping. Why you are not stopping the containers?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/testcontainers/testcontainers-java/issues/87#issuecomment-389835091,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABAIitGhLGvBtOhG78cyZUSKwSQnNZe7ks5tzV9bgaJpZM4HwB4A
.
It was my first thought, just wanted to confirm 😄
Thank you.
There is a nice hook, which is doing it: https://github.com/testcontainers/testcontainers-java/blob/master/core/src/main/java/org/testcontainers/utility/ResourceReaper.java#L362
@colinmorelli I did something along the lines of below pattern, which seems to work reasonably well without reliance on ClassRule mechanism (pattern is likely equally relevant for use in non-junit test frameworks):
public class PostgresContainer {
private static final PostgreSQLContainer container = new PostgreSQLContainer();
static {
container.start();
}
public static PostgreSQLContainer getContainer() {
return container;
}
}
Then you reference the static getContainer() method across your test suite whenever you need it, and it is an effective singleton for the test suite JVM in the usual case.
(updated based on @bsideup confirmation that ResourceReaper uses JVM-level shutdown listener)
@tom-haines actually, !container.isRunning() will never give false, and the shutdown hook is not needed, Testcontainers will take care of it :)
So it is as simple as:
public class PostgresContainer {
private static final PostgreSQLContainer container = new PostgreSQLContainer();
static {
container.start();
}
public static PostgreSQLContainer getContainer() {
return container;
}
}
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this is a mistake, please reply to this comment to keep it open. If there isn't one already, a PR to fix or at least reproduce the problem in a test case will always help us get back on track to tackle this.
Not stale - this is something we're always thinking about for the next breaking change release.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you believe this is a mistake, please reply to this comment to keep it open. If there isn't one already, a PR to fix or at least reproduce the problem in a test case will always help us get back on track to tackle this.
Just quoting @rnorth
Not stale - this is something we're always thinking about for the next breaking change release.
@rnorth Was redirected here by #1525 - although this ticket focusses on better support for other test frameworks, I would love to see for it to be completely test framework agnostic.
I was thinking of the use case where you run testcontainers as the dependency within your spring-boot app in development. I just do not want to bother with (re)starting containers when starting my app.
The idea is is that starting mvn spring-boot:run -Pdev will start the containers where the dev profile contains the the testcontainers dependency.
<profiles>
<profile>
<id>dev</id>
<dependencies>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
This actually already works - but having all junit Test classes inside the application in the IDE just makes things confusing.
The maven profile is there to avoid having this dependency included in the final artifact (don't want this in production, right).
Adding an exclusion block for junit also is not a solution - it fails with a "weird" compile time error
[ERROR] /Users/slyoldfox/Code/file-manager-module-test/src/main/java/com/samples/filemanager/FileManagerTestApplication.java:[78,61] cannot access org.junit.rules.TestRule
[ERROR] class file for org.junit.rules.TestRule not found
This is of course due to:
public class FailureDetectingExternalResource implements TestRule.
Ideally I see a wonderful use case for testcontainers (your should call it bootcontainers ;-)) - where it can be used outside test contexts to quickly boot containers from within the app.
Think spring-boot - for testcontainers ...
@bsideup thanks for the link and interesting read - but how does work around the junit dependency being pulled in? I assume you pulled in testcontainers as a compile time dependency to make this work?
Your final artifact would then have testcontainers (and all their transitive dependencies like junit) in it?
I am trying to avoid having junit (and testcontainers) on the classpath in anything else than the "dev" profile.
@slyoldfox as described in the article, the test application is in testCompile scope (where Testcontainers) is available.
@bsideup thanks for the clarification! :-) While I understand the setup now - and for the sake of discussion, your setup might work but poses some possible issues if your TestApplication includes test dependencies that interfere in development. Since you are executing this in testCompile scope, all the test dependencies will be included in your classpath - which is exactly what I want to try and avoid (I don't want assertj and mockito doing all their magic for example - even though they would probably do nothing harmful).
For me, your Initializer class should be in the compile scope instead of the testCompile scope. And the test should re-use the Initializer class from the compile scope (so the way around). This allows or re-use of this class in third party modules - if you intend to reuse this class in other third party projects.
Further more this Initializer class could then be configured by Spring Boot using @ConditionalOnClass annotations and setup by an *AutoConfiger class (specified in spring.factories). Which would allow early initialization of the containers and there would be no need to modify the SpringApplication.run(DemoApplication.class, args); contract.
Anyway all this won't work until the JUnit classes are decoupled from testcontainers - or until you include junit in compile scope.
It would make it a powerful tool though - outside of testing.
I don't want assertj and mockito doing all their magic for example - even though they would probably do nothing harmful
when you run psvm-like process from the test scope, there won't be any automagically applied Mockito or AssertJ code
Further more this Initializer class could then be configured by Spring Boot using @ConditionalOnClass annotations and setup by an *AutoConfiger class (specified in spring.factories)
That's just another option how to do that. You're free to use any mechanism available in Spring Boot.
For me, your Initializer class should be in the compile scope instead of the testCompile scope
You're free to put it wherever you like. Just keep in mind that Testcontainers is a library for... well... testing, so there is no guarantee that it won't have test-focused dependencies.
I'd personally advice against mixing production and development code.
Most helpful comment
AFAICT there's no reason the containers need to extend
TestRuledirectly. Instead, it seems it'd be fairly trivial to have the containers completely isolated fromJUnit, with manualstart/stopabilities (and potentially a Runtime hook to cleanup on shutdown. Then, it would be trivial to create integrations that could tie the engine into JUnit 4/5.I'm probably doing things a bit different than others, but personally I'm creating containers for postgres/rabbitmq during test instantiation, which is then shared between multiple tests (even with TestContainers, the overhead of restarting containers on every test run is too high). So, I'm not using any of the JUnit integration. That said, I still have to have JUnit 4 on the classpath to be able to use it (because it extends TestRule).