aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Test your business service Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Test your business service" Watch "Test your business service" New topic
Author

Test your business service

Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Hi all,

When I wanted to verify if my business service was working correctly I created the following test. It is not such a generic one as Roberto Perillo's Data class test, but I just want to share it with the JavaRanch community.

What's the purpose of the test? I create a few more threads than that I have records in my database file (35 threads, 31 records). Every thread tries to book a room. When a thread has successfully booked a room, a message is printed and it ends is run. So at the end of the program you should see 31 threads being able to book a room (in a random order) and 4 threads having to sleep this night on the street


Note: as you see it is primarly made for the URLyBird assignment (rooms), but of course it can be used with some very small changes for Bodgitt & Scraper too (just change "room" by "contractor" and you're done)

Have fun with it!
Kind regards,
Roel

[edit] added hasFinished-method to check if all threads are finished (instead of calling thread.join() which results in sequential processing) (thanks to Savas Aydin for making this remark)
[edit] used join again to wait until all threads are finished (thanks to Sean Keane)
[edit] only increment recNo when run is not ended (thanks to Fatih Onur)


SCJA, SCJP (1.4 | 5.0 | 6.0), SCJD
http://www.javaroe.be/
Andy Jung
Ranch Hand

Joined: Feb 07, 2010
Posts: 150
Hi Roel,

thanks for this test.
Can you please attach a link to Roberto's Data class test in this thread, it's missing yet?

Thanks,
Andy


SCJP, SCJD
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Hi Andy,

It is linked from the ScjdFaq, have a look there There you'll find my Ant build script (to wrap up you submission jar) and a test case (to check you didn't miss a file or forgot a must requirement) too.

Kind regards,
Roel
Carlos Morillo
Ranch Hand

Joined: Jun 06, 2009
Posts: 221

Hi Roel,


Thanks for sharing this!



Andy,

Roberto's Data class test is in the FAQ for this SCJD forum.


Best,


Carlos.


SCSA, OCA, SCJP 5.0, SCJD, CCDH, CCAH http://www.linkedin.com/in/carlosamorillo
Roberto Perillo
Bartender

Joined: Dec 28, 2007
Posts: 2267
    
    3

That's my good buddy Roel! I think it will be very helpful to everybody still developing the assignment.

Now, one idea that I had, there are 2 services we have to provide to the GUI, that is, to book rooms and to search for rooms. Maybe there could be another Thread that also searches for rooms? What do you think?

Also, I think this post could be placed in the SCJD faq!


Cheers, Bob "John Lennon" Perillo
SCJP, SCWCD, SCJD, SCBCD - Daileon: A Tool for Enabling Domain Annotations
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Roberto Perillo wrote:Maybe there could be another Thread that also searches for rooms? What do you think?
That is true, but it is hard to have a real test for that service method, because it depends on the content of the data file and on the assumptions you make.

I have another test case where I guanrantee 100% test coverage for my business service. And I test both search and booking methods, but I can't really share that one, because it is too closely tied to my own business service (and my assumptions). That's the reason why I can't share this test (and I also can't share the test of my Data class)

I will add a link to this test in the ScjdFaq today.

[edit] it has been linked from the ScjdFaq

Kind regards,
Roel
Savas Aydin
Greenhorn

Joined: Sep 09, 2011
Posts: 12
Hi Roel,

What is the purpose of "thread.join();" call. In order to test locking mechanism, I needed to remove it.

Thanks,
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

javadoc of the join-method wrote:Waits for this thread to die.

So the current thread (executing the main-method) will wait to finish until all threads to which it joined are finished.

A little example code:

If you run this little application you are guaranteed that end main will be the last statement printed. If you put thread.join(); into comments and you run the application again, this will not be the case anymore. So that should illustrate the purpose of the join().

In the program above I probably had some System.out.println("Done."); statement and that's why the thread.join() call is in there (because you want it only to be printed if all threads are finished). I modify the program above to add the print-statement.
But it should not make any difference at all. With or without the call it should work. So if you have to remove it in order to get your application functioning well, seems a bit strange to me. What happens when you don't remove the call?

And as a final note: this is not a test for your locking mechanism, this is just a test for your business service implementation. If you are looking for a test for the locking mechanism, use Roberto's Data Class Test (see ScjdFaq).

Hope it helps!
Savas Aydin
Greenhorn

Joined: Sep 09, 2011
Posts: 12
I just wanted to ensure bookRoom works correctly on multi-client environment. Without removing it, there is only one thread accessing to database at a time. I used Roberto's Unit Test Case too.

When i used Reberto's unit test, I needed to slow down the thread that creates other threads. Otherwise, I am getting OutOfMemoryError when i increase the counter to 2000. Do you think this is a memory leak. I just have record and lock Maps that can consume memory. Do you have any guess about what can be the leak?

Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

Savas Aydin wrote:Do you have any guess about what can be the leak?


Try profiling the code. This product here is also good.


SCJP (1.4 | 5.0), OCJP (6.0), OCMJD
Savas Aydin
Greenhorn

Joined: Sep 09, 2011
Posts: 12
Thanks for your suggestion. However, it is not reproducable when i use a profiler. I think it is not a memory leak issue. My code creates too much garbage object that slows down the code that calls Data medhods because of trimming. Therefore, the unit test can create new threads faster that it finalize them. This way, thread number exceeds the maximum.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Savas Aydin wrote:I just wanted to ensure bookRoom works correctly on multi-client environment.

This test is definitely what you need

So what are you experiencing if you run the code as-is (with the thread.join();) which makes you (or your code) unhappy?
Savas Aydin
Greenhorn

Joined: Sep 09, 2011
Posts: 12
Roel De Nijs wrote:
So what are you experiencing if you run the code as-is (with the thread.join();) which makes you (or your code) unhappy?


When join() is used, following code will suspend until current thread finishes. Thus, there will only be one single thread running at a time. But i want to test double booking is denied.

Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

You are correct! Trying to answer questions with your head full of mucus due to sinusitis is not a good idea. Totally my mistake, so my apologies for that.

I looked back to my original test case and in that test case I start my RMI-server, start all threads and then call System.exit(0) all from the main-method of my test case. So I could run this test case from my Ant build script as a test. Therefore it's needed that all threads are finished before the JVM is terminated and that's why the thread.join() call is made. But the drawback of that approach is, like you already mentioned, that only one single thread is running at a time. So I made some modifications to the test case which removes this drawback and guarantees a non-sequantial processing.
Sean Keane
Ranch Hand

Joined: Nov 03, 2010
Posts: 581

To get the main thread waiting for all the spawned off threads to finish, simply do this:
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Sean Keane wrote:To get the main thread waiting for all the spawned off threads to finish, simply do this

That was my initial thought to solve it, but I opted for the other approach, because I was not 100% sure it would solve it (and didn't make the effort to test it) (updated the test case)
Martin Vanyavchich
Ranch Hand

Joined: Sep 16, 2008
Posts: 241
Hi,

I've used the class provided by Roel to test my services and I've got 35 'booked no room' messages. After a good look at the code I've realized that we're always booking room with record number 0. So I deleted the int recNo = 0; in the run() method and I've just put private static int recNo = 0; at the top of the class, just under DB_PATH. Now the record number gets incremented, and rooms 0 trough 35 get booked.

Hope this didn't compromised the test in any way.


SCJP 6, OCMJD 6, OCPJWSD 6
I no good English.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Martin Vanyavchich wrote:After a good look at the code I've realized that we're always booking room with record number 0.

Are you sure you had a good lock. In the run-method recNo is initialized to 0. With every iteration (until endRun is set to true) recNo is incremented with 1 (line 62 in the code snippet in the OP).

If you are always booking record number 0 (comment line 62), you wouldn't see 35 'booked no room' messages, because one client should have booked room 0, all other threads shouldn't be able to book the room.

So your original output is not what you should expect. And your "fix" is also questionable: changing it into a class variable which will be modified by a bunch of threads (in a non thread-safe way). I don't see how this could fix your initial problem.

Martin Vanyavchich wrote:Now the record number gets incremented, and rooms 0 trough 35 get booked.

That's also weird. I don't think your database file contains 35 records at the start. My database file contains 31 rooms and that's why I used 35 as the number of threads. Because the expected output would be 31 rooms being booked, 4 clients without a booking. If you have e.g. a database file containing 28 records, you should have 28 bookings and 7 threads without a booking (and no 35 bookings)
Martin Vanyavchich
Ranch Hand

Joined: Sep 16, 2008
Posts: 241
Hey,

Roel De Nijs wrote:
If you are always booking record number 0 (comment line 62), you wouldn't see 35 'booked no room' messages, because one client should have booked room 0, all other threads shouldn't be able to book the room.

I start my record numbers with 1 and not 0 so I got an instant RecordNotFoundException, fixed my code to solve that problem.

Roel De Nijs wrote:
So your original output is not what you should expect. And your "fix" is also questionable: changing it into a class variable which will be modified by a bunch of threads (in a non thread-safe way). I don't see how this could fix your initial problem.

You're right my fix is realy bad. Should probably use an Integer and synchronize on it. I thought that we're trying to start 35 threads, that will try to book rooms 1 trough 35, and some will fail at it. That's why I made it into a class variable.

Roel De Nijs wrote:
Martin Vanyavchich wrote:Now the record number gets incremented, and rooms 0 trough 35 get booked.

That's also weird. I don't think your database file contains 35 records at the start.

You're right again, I got five record not found Exceptions.

I was hoping to submitt my assignment today and my face changed six different colors when the test failed . Now I've fixed all the problems in my code. Roel thank you for the test class, you really saved me, I owe you one
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Martin Vanyavchich wrote:Should probably use an Integer and synchronize on it. I thought that we're trying to start 35 threads, that will try to book rooms 1 trough 35, and some will fail at it. That's why I made it into a class variable.

No, you should just leave it as-is. You should just make 1 small modification: initialize recNo to 1 instead of 0, because you started record numbers with 1. This little thingy will solve the issue you had (35 'booked no room' messages), because now you won't have RNFE at the start of your application.
Intention of this test class is simply to stress test your business service implementation: 35 threads (clients) try to book a room and each thread starts with room 0 (or 1 in your case). Only one thread should be able to book a given room and a room can only be booked by 1 thread. When a thread has booked a room, it finishes and dies (because it encountered its sole reason to live: booking a room ). In the end a few threads (35 - number of records in your database file) won't have booked a room.

Martin Vanyavchich wrote:thank you for the test class

Glad to hear it was helpful for you.
Fatih Onur
Greenhorn

Joined: Oct 19, 2014
Posts: 1
First of all, thank you Roel for the very helpful testing code.

I would like to submit a bug fix regarding the testing code(line:62) for people who might be get mad to fix their own production code as I did.

With above change, you won't see your booking ids and and recNos in wrong order.
Roel De Nijs
Bartender

Joined: Jul 19, 2004
Posts: 5539
    
  13

Hi Fatih,

First of all, a warm welcome to the CodeRanch!

Fatih Onur wrote:I would like to submit a bug fix regarding the testing code(line:62) for people who might be get mad to fix their own production code as I did.

Bug confirmed and added your fix to testing code. Thanks! And sorry for the inconvenience of fixing your production code

Kind regards,
Roel
 
jQuery in Action, 2nd edition
 
subject: Test your business service