bypassing #Test dependsOnMethods due to failure - java

I have a question regarding the #Test(dependOnMethods{""})..
I want my tests to run in a particular order so I hit every test that I have written. The best way to do this so far, atleast that I have found, is the dependsOnMethods! However, since the tests to come after requires the one before it to pass, I cant run all of my tests and see which ones failed. My program just exits! So here is what I'm working with..
#Test(dependsOnMethods = {"shouldSelectAmountOfDoors"})
public void shouldSelectExtColor() throws InterruptedException{
sycOptionalInfoPage.selectExtColor("GREEN");
}
#Test(dependsOnMethods = {"shouldSelectExtColor"})
public void shouldSelectIntColor() throws InterruptedException{
sycOptionalInfoPage.selectIntColor("GOLD");
}
#Test(dependsOnMethods = {"shouldSelectIntColor"})
public void shouldEnterAComment() throws InterruptedException{
sycOptionalInfoPage.enterComments("<(*-<) <(*-*)> (>-*)> woot!");
takeABreakYo();
}
Boom. Very easy to understand and trusty POM! But, if my shouldSelectIntColor() fails due to a changed id from the dev team, I want the shouldEnterAComment to still run! How can I continue to keep my tests chained in a line, but still run after a failure? Thanks :)

You can use priority instead of dependsOnMethods to achieve what you want:
#Test(priority = 1)
public void shouldSelectIntColor() throws InterruptedException{
}
#Test(priority = 2)
public void shouldEnterAComment() throws InterruptedException{
}
Here if your shouldSelectIntColor method fails, it will still execute shouldEnterAComment test method.

You can use priority as mentioned or you can use run-always=true. Its called soft dependancy. This way your methods will still run even if the method before failed.

Related

How to test code that subscribes to an Uni?

I know that I can test a method that returns an Uni:
#Test
public void testUni() {
service.doSomething().invoke(data -> {
// run assertions
}).subscribe().withSubscriber(UniAssertSubscriber.create()).assertCompleted();
}
But what if I want to test the method that subscribes to the Uni itself? For example, consider this piece of code:
public void execute() {
service.reprocessAll().subscribe().with(
success -> log.info("Reprocessing ran successfully."),
error -> log.severe("Reprocessing failed: " + error.getMessage())
);
}
If I try to test it like this...
#Test
public void shouldLogSuccessAfterReprocessing() {
service.execute()
Mockito.verify(log, times(1)).success("Reprocessing ran successfully");
}
The test will fail due to a race condition. I mean, the test code will run before the actual code under test (the log.success call). So how can I tell the test to wait for the Uni to complete? Or how could I refactor this to make it testable?
The proper question would be how to design the code so that it is unit-testable which may lead a different answer than the one I will be writing here to respond to your current need.
Since the service#reprocessAll computation will be triggered on the background, and you have no means of controlling it behavior as your #service method simply returns void, you can block the calling unit runtime thread awaiting for the processing to finish:
#Test
public void shouldLogSuccessAfterReprocessing() throws Exception {
service.execute()
Thread.sleep(1000); // wait for reprocessAll to finish then proceed with assertions
Mockito.verify(log, times(1)).success("Reprocessing ran successfully");
}
For finer control, you can use the awaitiliy library for condition testing.

camel weaveAddLast() in before() will add many copies, not good

Am I the first one bumping into this? Is there a way I've overseen to reset the loaded context without writing too much code?
Problem:
#Before
public void before() throws Exception {
context.getRouteDefinition(MyRoute.ID).adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveAddLast().to("seda:endjob");
}
});
}
#Test
public void testOne(){}
#Test
public void testTwo(){}
will add the "seda:endjob" endpoint TWICE - one for each #Test because #Before will be called before every one. So it kind of makes sense, but I definitely hate it! ALL the examples I've been able to find, either have only one #Test (duh no problem) or do the weaving INSIDE the test which again avoids the problem (but repeats code if my weaving gets hairy)
What I do now is wrapping the weaving into many ugly custom checks, like this one:
if (getOriginalRoute().getOutputs().size() == 1) {
weaveAddLast().to("seda:endjob");
}
The question is then, is there a good way to reset the weaving? Or reload the RouteBuilder? Or something else, just without extra code?

junit detect if a test is the only one run

I have a test like this:
#Test public void testInfinite() {
while (true) {runSomeOtherTest();waitForSomeSignal();}
We have a spring context which takes a while to initialize - and with the above test and hotswapping - it means I can debug changes in seconds rather than waiting for a restart.
However, obviously checking this into the CI system is a bit of a problem, and of course something I've accidentally done several times. I'm wondering if it's possible (without changing the testrunner, because we are already using a custom one, that's hard to modify) to determine if it's the only test running. eg I want to be able to say
#Test public void testInfinite() {
if (!testIsTheOnlyTestWhichWillBeRun()) return; ...
So, bottom line - what I'm looking for is that if I right click on exactly that test and say run, in the IDE - it will do that - in all other cases - eg I right click and run the whole class - or I do it from gradle, or from CI - the test does nothing and just returns immediately.
You can evaluate a System property:
#Test public void testInfinite() {
if (!"true".equals(System.getProperty("junit.runloop"))) {
return;
}
}
In your IDE/local run, you can then run the test with -Djunit.runloop=true.
To not polute the test cases themselves, you could write a JUnit rule that does this:
public class TestInfinite implements TestRule {
#Override
public Statement apply(Statement base, Description description) {
return new Statement() {
public void evaluate() throws Throwable {
do {
base.evaluate();
} while ("true".equals(System.getProperty("junit.runloop")));
}
};
}
}
So in your test, you can attach them:
public class YourTest {
#Rule public TestInfinite = new TestInfinite();
#Test public void testInfinite() {
// this will be run once if property is not set,
// in an endless loop if it is
}
}

Integration test before others

I have a bunch of integration tests that need to have a database populated before running. This task takes about 30 minutes, so it is not feasible to run it before every test.
I'm using junit and I'd like to be able to annotate this one class with something so that it runs and completes before the others start. Is this possible?
(most of the annotations I found only work on methods, e.g. #Rule)
I've done this in the past by adding setup and teardown functions to the individual test classes, annotated with #BeforeClass and #AfterClass.
#BeforeClass
public static void setupBeforeClass() {
DatabasePopulater.populate();
}
#AfterClass
public static void tearDownAfterClass() {
DatabasePopulater.dePopulate();
}
If more than one test class requires the same setup to be done, the setup function can do a kind of reference counting to make sure they only do their work the first time it's called:
public class DatabasePopulater {
AtomicInteger invocations = new AtomicInteger();
....
public static void populate() {
if (0 == ivocations.getAndIncrement()) {
// Actually populate DB
}
}
public static void dePopulate() {
if (0 == ivocations.decrementAndGet()) {
// Actually clear DB
}
}
If you are using something like ant/gradle to execute the test suite, you could separate out the db population into a standalone java program and then have a depends="populateDB" on the junit task.

Selenium RC : Only one browser for all the tests?

I'm quite stuck right now, I don't understand why my code doesn't work as I need to. The fact is that each time there is a new test, it closes firefox and reopens it. That makes my tests take ages to realise... Could you tell me what I'm doing wrong ?
public class SeleniumTestLoginEntry extends SeleneseTestCase {
private String login="scLocator=//DynamicForm[ID=\"formulaire_login\"]/item[index=0||Class=TextItem]/element";
private String passwd="scLocator=//DynamicForm[ID=\"formulaire_login\"]/item[index=1||Class=PasswordItem]/element";
static public DefaultSelenium selenium;
public void setUp() throws Exception {
selenium = new DefaultSelenium("localhost", 4500, "*firefox", "http://localhost:9091/");
selenium.start();
}
public void testFields() throws Exception {
selenium.open("/agepro-prototype/login/Login.html");
selenium.type(login, "Unlogin");
selenium.type(passwd, "Unpassword");
Assert.assertEquals("Unlogin", selenium.getValue(login));
Assert.assertEquals("Unpassword", selenium.getValue(passwd));
selenium.click("scLocator=//ImgButton[ID=\"bouton_login\"]/");
}
public void testSameWindow() throws Exception {
selenium.open("/agepro-prototype/login/Login.html");
selenium.type(login, "truc");
Assert.assertEquals("truc", selenium.getValue(login));
}
public void tearDown() throws Exception {
selenium.stop();
}
}
I tried to put the annotations #BeforeClass and #AfterClass before the setUp() and tearDown, it doesn't change anything. Before there was an #Test before each test but this doesn't helped at all. May I ask you some help ? =)
Edit : Oh also I tried the selenium.open(blablabla) in the setUp() and not in the tests directly, same issue, doesn't change a thing.
Without using annotations, setUp() is going to run before every test (ie, twice).
It's not pretty, but you can create an initial test (which only runs once) and move the instantiation out of setUp() into the new test(). Keep in mind, though, that if that fails to create your selenium instance, then all your subsequent tests will also fail. Not great :)

Categories