Issue
I have never testing a program in Java, cause most of them are not multithreading, now the result is vary depends on time and luck, which is bad. I don't want my code not working when needed, example.
Currently my program I developed has worked as expected, and now since it is a concurrent programming with threads, I need to run like 100x and then a random error occurred. I did not want the program to to go infinite loop, instead of closing program.
Example Result:
Exit: Bus 37 exit the store
Size of Shop: 0
Cleaner : We're closing now!
Cleaner : We're closing now!
Depot : We're closing now!
Mechanics : We're closing now!
Mechanics : We're closing now!
Parking: We are closing now!
Process finished with exit code 0
This is the result when the program is OK
And sometimes the Result is this:
Ramp: Bus 37 using the ramp
Size of Shop: 2
Size of Shop: 2
Ramp: Bus 37 exit the ramp
Exit: Bus 37 exit the store
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
Size of Shop: 1
...
As seen here it goes forever, caused the program not exit. Is there a way to testing like 100x, make sure the program is close, which I can fix later on.
I just need the tools to make sure the Java will exit, as this is the condition for a successful program.
Solution
Make no mistake: you are asking for tools to act as band-aid to mediate a symptom.
That is the wrong approach. You want to fix the underlying bug. If your code doesn't behave deterministic, then most likely, because you put a bug into it. You are basically asking "how do I change my tests to ignore the problem". And the answer to that is: "you don't. you fix the issue".
So you should ask yourself instead: how can I fix the underlying problem?
There are many ways to get there, one of the most helpful ones in my eyes: look into using a same thread executor service.
The point is: in order to be able to test multi-threaded applications, you have to architect the program in ways to allow that.
Example: using "raw" thread objects is a bad idea. Instead, you want to clearly separate functionality. Into parts that work "on their own", to then have additional classes that take care of running things in parallel.
One helpful abstraction here: the ExecutorServce. You simply push "tasks" into that service, and the service can use multiple threads for processing. Thing is: using the aforementioned "same thread executor" you can enable yourself to run tests ... in a single threaded way. Then all that "random" can be greatly reduced.
Answered By - GhostCat
Answer Checked By - Mary Flores (JavaFixing Volunteer)