Oracle DB testing strategy - java

At work we are trying to simplify an application that was coded with an overkill use of Spring Remoting. This is how it works today:
(Controllers) Spring MVC -> Spring Remoting -> Hibernate
Everything is deployed in a single machine, Spring Remoting is not needed (never will be needed) and adds complexity to code maintenance. We want it out.
How to ensure everything works after our changes? Today we have 0% code coverage! We thought on creating integration tests to our controllers so when we remove Spring Remoting they should behave exactly the same. We thought on using a mix of Spring Test framework in conjunction with DBUnit to bring up Oracle up to a known state every test cycle.
Has anyone tried a similar solution? What are the drawbacks? Would you suggest any better alternative?

It always depends on the ratio effort / benefit that you are willing to take. You can get an almost 100% code coverage if you are really diligent and thorough. But that might be overkill too, especially when it comes to maintaining those tests. But your idea is good. I've done this a couple of times before with medium applications. This is what you should do:
Be sure that you have a well known test data set in the database at the beginning of every test in the test suite (you mentioned that yourself)
Since you're using Hibernate, you might also try using HSQLDB as a substitute for Oracle. That way, your tests will run a lot faster.
Create lots of independent little test cases covering most of your most valued functionality. You can always allow yourself to have some minor bugs in some remote and unimportant corners of the application.
Make sure those test cases all run before the refactoring.
Make sure you have a reference system that will not be touched by the refactoring, in order to be able to add new test cases, in case you think of something only later
Start refactoring, and while refactoring run all relevant tests that could be broken by the current refactoring step. Run the complete test suite once a night using tools such as jenkins.
That should work. If your application is a web application, then I can only recommend selenium. It has a nice jenkins integration and you can create hundreds of test cases by just clicking through your application in the browser (those clicks are recorded and a Java/Groovy/other language test script is generated).

In our Spring MVC / Hibernate (using v3.4) web app we use an Oracle database for integration testing.
To ensure that our database is in a known state each time the test suites are run, we set the following property in our test suite's persistence.xml:
<property name="hibernate.hbm2ddl.auto" value="create"/>
This ensures that the db schema is created each time our tests are run based on the Hibernate annotations in our classes. To populate our database with a know data set, we added a file named import.sql to our classpath with the appropriate SQL inserts. If you have the above property set, Hibernate will run the statements in import.sql on your database after creating the schema.

Related

Speed Up Hibernate Initialization

I'm having a Java EE application that runs on JBoss 7. In order to do TDD, I'm setting up embedded tests that use Arquillian with embedded Weld and a H2 embedded database.
This works fine, but the initial startup of Hibernate takes a considerable amount of time (5-10 seconds) and I haven't included all JPA entities yet. I have tried to use a persisted Oracle DB instead to avoid table creation, but it doesn't make much of a difference.
The main problem seems to be that Hibernate goes through all the entities and validates and prepares all the CRUD methods, named queries and so on.
Is there any way to tell Hibernate to do this lazily when needed (or not at all)? Most of the time, there will only be a subset of entities and queries involved in a test case, so I'd happily trade in execution time for start-up time while implementing.
Any ideas?
I know I could just use a subset of the entities, but it's sometimes difficult as they often have relations to other entities not needed in a test context. Or is there an easy way to 'deactivate' such relations to generate subsets of the database?
Clarification
It seams like it's not clear what my problem is, so I'll try to clarify:
I have set up a testing environment with Arquillian (embedded Weld) that sets up an embedded database (H2) to do JPA enabled testing
I would like to use this approach to do Test Driven Development (TDD), which means I will have the following workflow on my local developing machine:
Create test case
Run test case
If test case fails, implement necessary changes and go back to 2.
Normally, one will perform steps 2 and 3 a couple of times before finishing a feature which means that I will often run a single test from my IDE that has to set up the entire testing JVM with Arquillian, Weld, embedded DB and whatever to run just A SINGLE TEST.
So much for the scenario. Now I've noticed that running that single test takes around 10 seconds, which is not the end of the world, but rather long to do TDD. And when I further investigated, I've noticed that most of this time goes to Hibernate setting up its internal structures (it's not Weld, Arquillian, Schema creation or whatever, but Hibernate getting ready to provide an EntityManager).
So my question is: Is there a way to speed up hibernate initialization so I can drop these 10 seconds to maybe 1-2 seconds? I wouldn't care if it's sort of a hack (like keeping the testing JVM with hibernate alive during multiple manual test runs or deactivating some validations or optimizations of Hibernate). My only issue is the start up time for a single test. Consecutive tests run fine and fast, so I don't have a problem with full regression testing or with testing on my build server.
Hope that makes my case a bit clearer...
Let me guess, you are using junit library?
Database schema creation usually isn't the most time-consuming operation (although it depends on amount of entities).
Personally, if I were you, I would run all your JUnit tests with TestNG (yes, TestNG can run all JUnit tests out of the box) and would take a look at <your-module>/test-output/index.html (particularly its sections Chronological view and Times). Then you would know what operations are the most time-consuming. And with such information, you can go further.
Furthermore, a couple of items of advice:
Arquillian tests with a remote (or managed) containers are usually faster, because you start server only once.
H2 embedded database isn't a bad choice, really. Typically you don't have to abandon it (typically, because sometimes your application may use some of the target database features, that are not present in the H2).
There is Arquillian Suite Extension that lets you do deployment only once and reuse it across the test classes. In case of many tests, this extension can speed up tests execution significantly.
You can test your entities outside any container (so called standalone JPA with transaction-type="RESOURCE_LOCAL"). It is the fastest way, but suits well only for testing entities annotations, relations, queries and so on.
Edit
There is number of ways to do your task much better. Just a couple of points:
You don't have to re-create database every time. Even embedded databases (H2, HSQLDB, Derby) have server mode in which they last longer than JVM.
If Hibernate initialization bothers you, then do it once across the all tests (I mean keeping EntityManagerFactory between unit tests).
If you want to avoid a database creation, just use H2 in server mode and set hibernate to not do any changes (<property name="hibernate.hbm2ddl.auto" value="none" />)

What is the proper way to test a hibernate dialect?

I have written my own hibernate dialect for a RDBMS. What is the best way to test the dialect? Are there any testsuites/tests that could be helpful for me? What is the best way to make sure, that my implementation is correct/supports all necessary features?
This is purely from reading stuff from the Hibernate GitHub repos, not from experience with "doing" Hibernate testing. However, it may be sufficient to get you started ...
The Hibernate matrix testing framework allows you to run tests against specific database backends; see https://github.com/hibernate/hibernate-matrix-testing. The README.md file says how to configure the framework for a specific database.
The Hibernate ORM tree includes a number of tests for the core of Hibernate; see https://github.com/hibernate/hibernate-orm. The README.md for that project mentions Gradle tasks for running the tests. (I haven't looked at the available tests in detail, but since the ORM tree includes the "dialect" classes for a range of database, I would imagine that includes the corresponding tests.)
Hibernate's build and test framework is implemented using Gradle, so I expect that you will need to get your head around that technology to figure out how it all works.
Not aware of any such suite or tests. To start with:
test various query scenarios & see if queries generated are running fine for that DB - when ran standalone.
test exceptions expected in all scenarios.
check on how it behaves for a new/old version of the DB driver.
Best of luck!

Run Java Spring application from eclipse

I'm working on a project at work that runs on the spring framework and requires a connection to an oracle database at all times. When I want to test a new method I have to stop my server, rebuild, start the server, then launch my application.
My question is is there any way to run my application without having to launch it every time? I'm okay with having to restart the server but I'm trying to eliminate launching the application every time.
Cheers.
What you seek are integration tests. You need to break your application into individual pieces and test their functionality against the oracle database bit by bit. These little pieces can be tested by certain testing technologies such as the popular JUnit.
All the pieces that you need should only depend on the data source and whatever other collaborating beans that are needed. Break your bean definitions apart such that they are small and only depend on very few beans, tracking back to the data source bean. You can then use JUnit (or whatever testing technology you'd like) and Spring's testing annotations to make small application contexts
See this section of the Spring reference manual for more information:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/testing.html
When you have tests, you don't actually run the application - you run a part of it to verify its behavior individually. You can then add tests that test the pieces together, and eventually your confidence in the application will rise.

Best practice for testing Hibernate mappings

I am wondering what people have found their best practice to be for testing Hibernate mappings and queries ?
This cannot be done with Unit Testing, so my experience has been to write Integration Tests that solely tests the DAO layer downwards. This way I can fully test each Insert / Update / Delete / ReadQueries without testing the full end-to-end solution.
Whenever the Integration test suite is run it will:-
Drop and re-create the database.
Run an import SQL script that contains a subset of data.
Run each test in a Transactional context that rolls back the transaction. Therefore it can be run multiple times as an independent test, or and as part of a suite, and the same result is returned as the database is always in a known state.
I never test against a different "in memory" database, as there is always an equivalent development database to test against.
I have never had the need to use DBUnit.
Never use DbUnit for this. It's way too much overhead for this level of testing.
Especially if you're using Spring in your app, check out the Spring Test Framework to help manage your data-access tests, particularly the transaction management features.
An "equivalent development database" is fine, but an in-memory H2 database will blow away anything else for speed. That's important because, while the unit/integration status of these tests may be contested, they're tests you want to run a lot, so they need to be as fast as possible.
So my DAO tests look like this:
Spring manages the SessionFactory and TransactionManager.
Spring handles all transactions for test methods.
Hibernate creates the current schema in an in-memory H2 database.
Test all the save, load, delete, and find methods, doing field-for-field comparison on before and after objects. (E.g. create object foo1, save it, load it as foo2, verify foo1 and foo2 contain identical values.)
Very lightweight and useful for quick feedback.
If you don't depend on proprietary rdbms features (triggers, stored procedures etc) then you can easily and fully test your DAOs using JUnit and an in memory database like HSQLDB. You'll need some rudimentary hibernate.cfg.xml emulation via a class (to initialize hibernate with HSQLDB, load the hbm.xml files you want) and then pass the provided datasource to your daos.
Works well and provides real value to the development lifecycle.
The way I do it is pretty similar with your own, with the exception of actually using in-memory data-bases, like HSQLDB. It's faster and more portable than having a real database configured (one that runs in a standalone server). It's true that for certain more advanced features HSQLDB won't work as it simply does not support them, but I've noticed that I hardly run into those when just integration testing my data access layer. However if this is the case, I like to use the "jar" version of mysql, which allows me to start a fully functional MYSql server from java, and shut it down when I'm done. This is not very practical as the jar file is quite big :
http://dev.mysql.com/doc/refman/5.0/en/connector-mxj-configuration-java-object.html
but it's still useful in some instances.

How to unit test legacy J2EE application

This may sound like a vague question but I am looking for some specif pointers.
Our J2EE app is built on Struts2 + Plain Servlets + JSP + iBatis + Oracle
I would prefer to write unit tests in Scala so that I can learn the language on the side as well
What would I need to be able to verify that a spcific column is displayed in the JSP following some specific steps
Click on a link. select some parameters and submit the page to the servlet
Verify that the next page has a specific column inside its <table> tag.
What would I need to create mock requests for the serlvet?
I am trying to write tests like above in addition to core business functionality tests however, the problem is that I am trying to wrap legacy code in unit tests and the code of course is not designed for unit testing.
I wouldn't call this unit testing. As you are trying to test integration of several units. Also it's rather hard to create a unit test for a JSP becuase it has many context dependencies available only when you are in the container.
Instead I would advice writing some automated functional tests that are executed against running (deployed) application.
Frameworks like Selenium may be of great help here as they allow to simulate real user behaviour and make asserts against produced HTML code.
EDIT: Another approach here may be to:
start an embedded servlet container like Jetty within your test code
deploy all your plain servlets and JSPs to that
replace Oracle database with in-memory database like HSQL or Derby
populate it with some test data using DBUnit
and then again use either Selenium (which has Java binding) or HttpUnit to make requests and asserts against generated HTML code.
But again it will not be a unit test, but rather an integration test.
Like everyone said, your not really talking about unit testing. You're talking about functional testing. I'd think hard about what your real goals are. What is driving this push for automated testing? Does the application have configuration issues(i.e. its hard to configure so some parts work and others don't). This might justify building a smoke test suite in selenium targeting your pain pages and test cases. This will also help detect regression bugs.
As for the legacy concerns. No application is beyond help. If you are running front end tests in selenium then it doesn't matter how the code is written as long as its parseable HTML.
As for your actual server side code. You just gotta roll Andy Dufresne style. As you fix bugs and add functionality code with Test Driven Development principles in mind. Rework code that relates to your changes and add unit tests. You'd be surprised at how fast a legacy app can come around if you keep chipping away at it.

Categories