Pinging the result of a java function - java

so I have a function that deletes some object, thing. This can take a while, like a half hour ish, and I want to check if it is successfully deleted.
#Test
public void successfulThingDelete(){
Thing thing = new Thing();
deleteThing(thing);
if (thing.getStatus() == 'deleted'){
pass
}
else {
fail
}
I want to be able to continually check the status of thing (i.e thing.getStatus()) and pass the test if it is deleted. But if a certain time elapses and it's not deleted then the code has failed and it should fail. I'm assuming I need to introduce a new thread for this pinging of the status but I'm not sure how to add that within this method. Thanks for any help!

I would go for awaitility. With that you can write tests like
#Test
public void updatesCustomerStatus() throws Exception {
// Publish an asynchronous event:
publishEvent(updateCustomerStatusEvent);
// Awaitility lets you wait until the asynchronous operation completes:
await().atMost(5, SECONDS).until(customerStatusIsUpdated());
...
}

I'm guessing that this is a Junit test. The Test annotation allows a timeout attribute in the form "...#Test(timeout=1000)..." - the value is in milliseconds. So calculate the milliseconds in thirty minutes - 1800000 and use that. Junit will fail the test if it isn't finished in that time.
#Test(timeout=1800000)
public void successfulThingDelete(){...
If the test runs its course and finishes before the time limit then the usual coded assertions happen and the test ends. if the test actions take longer then Junit will interrupt whatever's running and fail the test overall.
Ref - https://github.com/junit-team/junit4/wiki/timeout-for-tests

Related

Running TestNG suite with multiple scripts with a time delay between each script?

I have a testng suite with 100 selenium scripts. My app can only handle 10 scripts per second, so I am running into page load issues and element not found exceptions. Is there a way to tweak testng implementation programmatically to add a delay of 1-2 seconds between each script?
I tried -
getting thread id and trying to Thread.sleep for 1 second before webdriver initialization, didn't work
initialize a new thread, put a method that sleeps for 1 sec in it and call this method depending upon thread id/name but it didn't work, testng returns a unique thread id but I'm unable to get a hold of it. I'm unable to counter my thread count with what testng has in its context
my script looks like this
public class MyScript implements MyInterface {
#Test
public myTest(){
initializeWebdriver();
//test something
}
}
public Interface MyInterface {
public void initializeWebdriver(){
//trying to add logic to initialize chromedricer based on testng thread id but unable to
int id = Thread.currentThread().getId();
if(id>10){
//add 1 sec delay for each script after 10 scripts
Thread.sleep(id*1000);
}
driver = new ChromeDriver();
}
}
Notes -
running sequentially works but it defeats my purpose
setting thread-count=10 works fine within the applciation performance limits but I have to run all 100 scripts within timeOut=30minutes. I have longer running scripts that always break because of the timeout. So only looking for some ideas or direction where I can implement a Listener or a helper to get a hold of session id or thread id from testng ITestContext or another testng listener and add a delay

Is it a bad practice to test the flow of logic by log statements?

I have a logic that does something like this that I want to test out:
public void doSomething(int num) {
var list = service.method1(num);
if (!list.isEmpty()) {
// Flow 1
LOG.info("List exists for {}", num);
doAnotherThing(num);
} else {
// Flow 2
LOG.info("No list found for {}", num);
}
}
public void doAnotherThing(int num) {
Optional<Foo> optionalFoo = anotherService.get(num);
optionalFoo.ifPresentOrElse(
foo -> {
if (!foo.type().equals("no")) {
// Flow 3
anotherService.filter(foo.getFilter());
} else {
// Flow 4
LOG.info("Foo is type {} - skipping", foo.type());
}
},
// Flow 5
() -> LOG.info("No foo found for {} - skipping", num));
}
For each test that'll test out different flow, my first thought was to Mockito.verify() to see if they were called or not. So to test out Flow 1, I would verify that anotherService.get() was called inside doAnotherThing(). And to test out Flow 2, I would verify that anotherService.get() was never called. This would've been fine except for Flow 4 and Flow 5. They would both invoke anotherService.get() once but not anything else.
Because of that, I've created a class to capture logs in tests. This would check to see if certain logs were logged and I would be able to see by it which flow it landed on. But I wanted to ask: is this a bad practice? I would combine this with verify() so that on flows that can be reached by verify() will take that as higher precedence.
One downside to this would be that the tests would rely on the log messages being correct so it would be a bit unstable. To account for that issue, I thought about taking some of these log messages out as a protected static variable that the tests can also use so the message would remain the same between the methods and the respective tests. This way, only the flow would be tested.
If the answer is that it is a bad practice, I would appreciate any tips on how to test out Flow 4 and Flow 5.
Log statements are usually not part of the logic to test but just a tool for ops. They should be adjusted to optimize ops (not too much info, not too few), so that you can quickly find out if and where something went wrong, if something went wrong. The exact text, the log levels and the number of log statements should not be considered as something stable to rely your tests on. Otherwise it will make it harder to change the logging concept.

Need help on writing a junit test for a function which is returning Flux stream as output

I need help in writing unit test for a function that is returning Flux stream as output.
I have tried using the StepVerifier but I guess I am using it in the wrong way.
In need to test the following function.
public Flux<List<String>> streamCompletedScansAfterLastSubmit(#PathVariable("username") String username) {
Flux<Long> interval = Flux.interval(Duration.ofSeconds(5));
Flux<List<String>> completeScans = Flux.fromStream(Stream.generate(() -> scanService.getCompletedScansAfterLastSubmitForUser(username)));
return Flux.zip(interval, completeScans).map(Tuple2::getT2);
}
What I have tried is
public void shouldPublishTheAssessmentStatusOnceFinished() {
when(scanService.getCompletedScansAfterLastSubmitForUser(Mockito.anyString())).thenReturn(Arrays.asList("Scan1:Success"));
StepVerifier.create(apiScanController.streamCompletedScansAfterLastSubmit("quays_ka"))
.expectSubscription()
.expectNext(Arrays.asList("Scan1:Success"))
.verifyComplete();
}
I am getting error:
java.lang.AssertionError: expectation "expectComplete" failed (expected: onComplete(); actual: onNext([Scan1:Success]))
Somehow the service method gets called twice (I checked that using doAnswer)
Stream.generate(Supplier) generates an infinite Stream, so completeScans is infinite too.
Since interval is also infinite, with the mock service the zipping of the two results in a Flux that emits ["Scan1:Success"] every 5 second.
On the contrary, your StepVerifier expects a very finite Flux of a single list before termination, so it fails as soon as it sees a second occurrence of the list.

Jbpm6 . Asynchronous workitem and retry

Let me come directly to use case.
I am having a number of work-items in my process say A,B,C. It starts in A--->B--->C order.
In my case, B is a call to a 3rd party web service. C should process only if B is success. if the call to the web-service fails, system should retry after 5 min. The number of retries are limited to 3.
How can I achieve this using Jbpm6.?
Some options that I understand from doc are,
1) I can use a work item handler. Inside work item, I will start another thread which will do the retries and finally it calls the completeWrokItem() method. But in this case my process engine thread will wait unnecessarily for the completeWrokItem() call.
2)I can use command for retry . But if I call command it will execute in another thread and the process thread will execute C. Which is not a desirable way
How can I create a process so that, B will execute in back-end and will notify the engine that it can continue executing C?
Please advice.
Thanks in advance.
Please comment if my question is not clear enough to answer.
Your question is not completely clear; however, I provide an answer to hopefully provide some clarity:
For asynchronous execution, you should follow guidelines in documentation: JBMP 6.0 Async Documentation
Given your processes flow, if you use a Command and a process defined as: A->B->C; C will not start until the command completes.
To have commands run in parallel, you use parallel branches. In below pic, if Script1 and Script2 were commands they would execute in parallel, and Email would only execute once both Scripts complete:
A command signals complete by simply returning from execute method:
public ExecutionResults execute(CommandContext ctx) throws Exception {
// Set results if exist. Otherwise, return empty ExecutionResults.
ExecutionResults results = new ExecutionResults();
// This would match the name of an output parameter for the work item.
// results.setData("result", "result data");
logger.info("Command finished execution: " + this.getClass());
logger.debug("Results of executing command: ", results);
return results;
}
`
Add a XOR gateway after the node B, Add script to of the node B and set the status and retry_count of web-service(if success, status_b = true; if failed, status_b = false and retry_count ++),
XOR go to C if the retry_count>=3 or status_b == true
else go to B again

How do I perform a Unit Test using threads? [duplicate]

This question already has answers here:
How should I unit test multithreaded code?
(29 answers)
Closed 5 years ago.
Executive Summary: When assertion errors are thrown in the threads, the unit test doesn't die. This makes sense, since one thread shouldn't be allowed to crash another thread. The question is how do I either 1) make the whole test fail when the first of the helper threads crashes or 2) loop through and determine the state of each thread after they have all completed (see code below). One way of doing the latter is by having a per thread status variable, e.g., "boolean[] statuses" and have "statuses[i] == false" mean that the thread failed (this could be extended to capture more information). However, that is not what I want: I want it to fail just like any other unit test when the assertion errors are thrown. Is this even possible? Is it desirable?
I got bored and I decided to spawn a bunch of threads in my unit test and then have them call a service method, just for the heck of it. The code looks approximately like:
Thread[] threads = new Thread[MAX_THREADS];
for( int i = 0; i < threads.length; i++ ) {
threads[i] = new Thread( new Runnable() {
private final int ID = threadIdSequenceNumber++;
public void run() {
try {
resultRefs[ID] = runTest( Integer.toString( ID ) ); // returns an object
}
catch( Throwable t ) {
// this code is EVIL - it catches even
// Errors - don't copy it - more on this below
final String message = "error testing thread with id => "
+ ID;
logger.debug( message, t );
throw new IllegalStateException( message, t );
// need to wrap throwable in a
// run time exception so it will compile
}
}
} );
}
After this, we will loop through the array of threads and start each one. After that we will wait for them all to finish. Finally, we will perform some checks on the result references.
for( Thread thread : threads )
thread.start();
logger.debug( "waiting for threads to finish ..." );
boolean done = false;
while( !done ) {
done = true;
for( Thread thread : threads )
if( thread.isAlive() )
done = false;
}
for( int i = 0; i < resultRefs.length; i++ ) {
assertTrue( "you've got the world messed, dawg!",
myCondition(resultRefs[i]) );
Here's the problem. Did you notice that nasty try-catch-throwable block? I just added that as a temporary hack so I could see what was going on. In runTest( String ) a few assertions are made, e.g., assertNotNull( null ), but since it is in a different thread, it doesn't cause the unit test to fail!!!!
My guess is that we will need to somehow iterate over the threads array, check the status of each, and manually cause an assertion error if the thread terminated in a nasty way. What's the name of the method that gives this information (the stack trace of the dead thread).
Concurrency is one of those things that are very difficult to unit test. If you are just trying to test that the code inside each thread is doing what it is supposed to test, may be you should just test this code isolated of the context.
If in this example the threads collaborate to reach a result, may be you can test that collaboration without using threads. That would be done by executing all the collaborative parts sequentially.
If you want to test for race conditions and these kind of things, unit testing is not the best way. You will get tests that sometimes fail and sometimes donĀ“t fail.
To summarize, I think that may be your problem is that you are unit testing in a level too high.
Hope this helps
The Google Testing Blog had an excellent article on this subject that's well worth reading: http://googletesting.blogspot.com/2008/08/tott-sleeping-synchronization.html
It's written in Python, but I think the principles are directly transferable to Java.
Unit testing in a multithreaded environment is tough... so some adjustments need to be made. Unit tests must be repeatable.. deterministic. As a result anything with multiple threads fails this criteria. Tests with multiple threads also tend to be slow.
I'd either try to see if I can get by with testing on a single thread.. does the logic under test really need multiple threads.
If that doesn't work, go with the member variable approach that you can check against an expected value at the end of the test, when all the threads have finished running.
Hey seems like there's another question just like this. Check my post for a link to a longer discussion at the tdd yahoogroup
Unit testing a multithreaded application?
Your runnable wrapper should be passing the exception object back to your test class and then you can store them in a collection. When all the tests are finish you can test the collection. If it isn't empty, iterate over each of the exceptions and .printStackTrace() then fail.
Implement a UncaughtExceptionHandler that sets some flags (which the Threads peridocially check) and set it on each Thread.
Another popular option for Junit concurrent thread testing is Matthieu Carbou's method using a custom JunitRunner and a simple annotation.
See the full documentation
It is possible making the unit test to fail, by using a special synchronization object. Take a look at the following article:
Sprinkler - Advanced synchronization object
I'll try to explain the main points here.
You want to be able to externalize internal threads failures to the main thread, which, in your case is the test. So you have to use a shared object/lock that both the internal thread and the test will use to sync each other.
See the following test - it creates a thread which simulates a thrown exception by calling a shared object named Sprinkler.
The main thread (the test) is blocked on Sprinkler.getInstance().await(CONTEXT, 10000)
which, by the time release is called - will be free and catch the thrown exception.
In the catch block you can write the assert which fails the test.
#Test
public void testAwait_InnerThreadExternalizeException() {
final int CONTEXT = 1;
final String EXCEPTION_MESSAGE = "test inner thread exception message";
// release will occur sometime in the future - simulate exception in the releaser thread
ExecutorServiceFactory.getCachedThreadPoolExecutor().submit(new Callable<void>() {
#Override
public Void call() throws Exception {
Sprinkler.getInstance().release(CONTEXT, new RuntimeException(EXCEPTION_MESSAGE));
return null;
}
});
Throwable thrown = null;
try {
Sprinkler.getInstance().await(CONTEXT, 10000);
} catch (Throwable t) {
// if the releaser thread delivers exception it will be externelized to this thread
thrown = t;
}
Assert.assertTrue(thrown instanceof SprinklerException);
Assert.assertEquals(EXCEPTION_MESSAGE, thrown.getCause().getMessage());
}

Categories

Resources