how to quickly create a test database for Cucumber-jvm? - java

I am using cucumber-jvm to test the behaviour of the legacy system I'm working on at work. I have to use Java 1.5 and Hibernate 3.3, upgrading is not an option. Since, during my tests, it stores some objects in the database, I have created a new development database.
What bothers me is that I have to manually drop the records (using a sql script) everytime I'll rerun my tests, or they'll fail. And anyone else wanting to run them would have to do the same. I want to quickly and automatically clean my test database, by either:
Creating an empty database and populating it with what I need, or
Using an already existing database, droping the records before starting the tests.
What I have so far: I'm using the cucumber-junit plugin, and the RunTests class redirects to my test database:
#RunWith(Cucumber.class)
#Cucumber.Options(
features = "test/resources/cucumber",
format = "html:target/cucumber"
)
public class RunTests {
private static Configuration configuration;
#BeforeClass
public static void preparaBase() {
// gets the mapped configuration to the db
configuration = HibernateUtil.getConfiguration();
configuration.setProperty("hibernate.connection.url", "test-db-url");
configuration.setProperty("hibernate.connection.username", "user");
configuration.setProperty("hibernate.connection.password", "pass");
// configuration.setProperty("hibernate.hbm2ddl.auto", "create-drop");
// rebuilds the configuration using my test database
HibernateUtil.rebuildSessionFactory(configuration);
}
}
I have tried using the hibernate.hbm2ddl.auto property with the create-drop value and using the import.sql file to prepare the database, but it takes ages to start the tests and it seems that it's not detecting my import.sql file.
Sadly, using Maven and its excellent maven-sql-plugin is not an option (I have suggested a switch to Maven, to no avail). Is there an alternative?

I did it!
I used this ScriptRunner class as such:
#RunWith(Cucumber.class)
#Cucumber.Options(
features = "test/resources/cucumber",
format = "html:target/cucumber"
)
public class RunTests {
private static Configuration configuration;
String url = "test-db-url";
String user = "user";
String pass = "pass";
#BeforeClass
public static void preparaBase() {
// gets the mapped configuration to the db
configuration = HibernateUtil.getConfiguration();
configuration.setProperty("hibernate.connection.url", url);
configuration.setProperty("hibernate.connection.username", user);
configuration.setProperty("hibernate.connection.password", pass);
// rebuilds the configuration using my test database
HibernateUtil.rebuildSessionFactory(configuration);
// executes a script stored in test/resources/cucumber
try {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, user, pass);
ScriptRunner runner = new ScriptRunner(conn, false, true);
runner.runScript(new BufferedReader(new FileReader("test/resources/cucumber/db.sql")));
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}

Related

Connecting mongodb to java project in Eclipse IDE (MacOS)

I'm trying to connect mongodb to my java project in eclipse. I've mentioned the code I've written following some instructions on youtube and the official mongodb documentation.
Below are the .jar files I've added to the project build path.
Project Properties/Build Path/JRE Files
package mongoConnect;
import com.mongodb.*;
import com.mongodb.client.MongoClients;
#SuppressWarnings("unused")
public class MongoDatabase {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
com.mongodb.client.MongoClient client = MongoClients.create("mongodb://localhost:27017");
DB db1 = mongo.getDB("collegemanagementsystem");
//error saying "mongo cannot be resolved" in mongo.getDB
DBCollection col1 = db1.getCollection("Student");
BasicDBObject d1 = new BasicDBObject("name", "Sabiha").append("age", "23");
BasicDBObject d2 = new BasicDBObject("name", "Abdullah").append("age", "25");
col1.insert(d1);
col1.insert(d2);
DBCursor cur = col1.find();
while (cur.hasNext()) {
System.out.println(cur.next());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The Code
I do have mongodb compass installed if that helps. I also have a local database created in mongodb.
Mongodb Connection in Mongodb Compass
My questions are:
Is this method different to connecting by jdbc or is this the jdbc method for connecting database to java project?
How can I resolve this issue?
If this is not the jdbc method how can I connect mongodb to my java project with the jdbc method?
Error Message

Completely unloading a JDBC driver in Java

I have an application that uses Java, mybatis, and SQL Anywhere. Because of some circumstances, I have to manually load in the SQLA driver jar at runtime. I got this working with this code:
public static URLClassLoader ucl;
public static Driver saDriver;
public static final void loadSqlAnywhere(SqlAnywhereVersions version)
{
if (saDriver == null)
{
try
{
File jarPath = "path\\to\\sajdbc4.jar";
URL jarUrl = new URL("jar:file:" + jarPath.getAbsolutePath() + "!/");
String driverClass = "sap.jdbc4.sqlanywhere.IDriver";
ucl = URLClassLoader.newInstance(new URL[]{ jarUrl });
saDriver = new DriverShim((Driver) Class.forName(driverClass, true, ucl).newInstance());
DriverManager.registerDriver(saDriver);
}
catch (Exception ex)
{
// Could not load SQL Anywhere driver
}
}
}
While the application is running, it's possible for SQL Anywhere to be upgraded. So, I need to completely unload the old driver, let the update happen, then init with the latest jar. I tried this:
private static List<SqlSession> sessions = new ArrayList<>();
private static SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder();
public static final void unloadSqlAnywhere()
{
if (saDriver != null)
{
// Close out any existing sessions
for (SqlSession session : sessions)
{
session.close();
}
sessions.clear();
// Kill the session factory
sessionFactory = null;
try
{
DriverManager.deregisterDriver(saDriver);
saDriver = null;
ucl.close();
ucl = null;
}
catch (Exception ex)
{
// Failed to unregister SQL Anywhere driver
}
}
}
But using jprofiler, I can see that DriverManager is still referencing sap.jdbc4.sqlanywhere.IDriver, which is causing the SQL Anywhere upgrade to kill my application.
Is there something more I can do to ensure all driver references are removed? Or is there a better way to go about this?
Most JDBC drivers auto-register themselves, e.g. you used to just have to call Class.forName() to load the driver class, and that would auto-register it.
Nowadays you don't even have to do that anymore, since they use the service framework to auto-register by simply being on the classpath, but since your JDBC jar file is not on the classpath, that doesn't apply here.
Since you also register the driver, it is registered twice, and when you deregister, you only remove the registration you created, not the one that was auto-registered.
To remove the auto-registered instance, you have to enumerate all registered drivers to find the instance to deregister:
// Any Java version
for (Enumeration<Driver> e = DriverManager.getDrivers(); e.hasMoreElements(); ) {
Driver driver = e.nextElement();
if (driver.getClass().getName().equals("sap.jdbc4.sqlanywhere.IDriver"))
DriverManager.deregisterDriver(driver);
}
// Java 9+
Optional<Driver> driver = DriverManager.drivers()
.filter(d -> d.getClass().getName().equals("sap.jdbc4.sqlanywhere.IDriver"))
.findAny();
if (driver.isPresent())
DriverManager.deregisterDriver(driver.get());

Testing multiple environments with different data - best practice

I need to be able to run the same tests on different environments (max 3) but with different data for each one.
I have a test method:
#Test (groups = "core", description = "Login: Valid log in")
public void validLogin() {
User user = UserData.user_2();
loginPage.logOn(user);
}
In the UserData class I have:
public static User user_2() {
return new User().newUser("user2", "password");
}
"user2" does not exist on all environments. I may not be able to change the data that is available on all of the environments to match the test data.
The tests will be executed either using Maven and TestNg so I can send in the parameter for the execution environment.
My initial thought is to use:
public static User user_2() {
switch(env) {
case "env1": return new User().newUser("user2", "password"); break;
case "env2": return new User().newUser("user2Z", "password"); break;
case "env3": return new User().newUser("user2X", "password"); break;
}
I have a limited number of data classes and methods (<100) but several thousand tests.
What is the best way of setting up and handling the data required for testing against the different environments?
When it comes to different users ,
You always wish that all my test cases should remain as it is and with minimal change.
So this is what i follow.
I create a file lets say username.properties file in eclipse.
username=xyz#gmail.com
password=passswd1
You can create multiple users here with name i.e.
rohan=rohan#gmail.com
rohan's password: rohan
Now we need to call this file in our class.
See below example.
Main test
SignInPage.SendkeysMethodForSignInPAgeForPropertyFile(driver, By.cssSelector("input[id='Email']") , "username" );
SignInPage.SendkeysMethodForSignInPAgeForPropertyFile(driver, By.cssSelector("input[id='Passwd'][type='password']"), "password");
So here username will be taken from properties file.
This will go to SendkeysMethodForSignInPAgeForPropertyFile which is:
public class SignInPage {
public void SendkeysMethodForSignInPAgeForPropertyFile(WebDriver driver, By by, String Text) {
WebUtils.SendkeysForPropertyFile(driver,by, Text);
}
}
Which will go to SendkeysForPropertyFile method as:
public static void SendkeysForPropertyFile(WebDriver driver, By by, String Text) {
ReadFileData File = new ReadFileData();
Properties Values = File.ReadFile();
WebElement Element = driver.findElement(by);
Element.clear();
if (Text == "username"){
Element.sendKeys(Values.getProperty("username"));
}
else {
Element.sendKeys(Values.getProperty("password"));
}
Which will read from ReadFileData() class which is:
public class ReadFileData {
public Properties ReadFile() {
File file = new File("D:\\Selenium\\Gmail_Web_UI\\Loginproperty.properties");
FileInputStream fileInput = null;
try {
fileInput = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Properties prop = new Properties();
//load properties file
try {
prop.load(fileInput);
} catch (IOException e) {
e.printStackTrace();
}
return prop;
}
This helps to keep our username and password safe in a single file.
Reply to me for further query. Happy Learning :-)

add external jars in spring - java

I am new to spring, I am trying a simple web dynamic application getting data from database and showing on front end using impala.
This is connector class :
private static final String IMPALAD_HOST = "host";
private static final String IMPALAD_JDBC_PORT = "port";
private static final String CONNECTION_URL = "jdbc:hive2://" + IMPALAD_HOST + ':' + IMPALAD_JDBC_PORT + "/;auth=noSasl";
private static final String JDBC_DRIVER_NAME = "org.apache.hive.jdbc.HiveDriver";
public Connection getConnection() throws ClassNotFoundException{
Connection con = null;
try {
Class.forName(JDBC_DRIVER_NAME);
con = DriverManager.getConnection(CONNECTION_URL,"","");
}catch (SQLException e) {
e.printStackTrace();
}
return con;
}`
HIve-connector jar is added in the java build path in eclipse. getConnection() works if i call it from a main method of a java class, but getConnection() gives hive driver not found exception if i call this method from jsp page. :
java.lang.ClassNotFoundException: org.apache.hive.jdbc.HiveDriver
You are not having the hive-jdbc.jar in your webapplication archive. i.e. war file. it is being missed while packaging the application.You should place it in the WEB-INF/lib directory. Please also ensure that you also add it in the deployment assembly of the eclipse project.
It works when you run the main class because the hive-jdbc.jar is configured in the build path. It is different from webapplication perspective.
Note: ClassNotFoundException shouldn't be thrown unless you are going to handle it. You should have all the required jars in your application package during runtime in classpath.
You are using the wrong Driver-Class.
Use org.apache.hadoop.hive.jdbc.HiveDriverinstead.

How to use MongodbJobStore (via file quartz.properties) connect to mongodb in project java webapplication?

I've issuse with configure file quartz.properties connect to mongodb.
this is my file quartz.properties
#specify the jobstore used
org.quartz.jobStore.class=com.novemberain.quartz.mongodb.MongoDBJobStore
org.quartz.jobStore.mongoUri=mongodb://localhost:27017
#The datasource for the jobstore that is to be used
org.quartz.jobStore.dbName=myds
org.quartz.jobStore.addresses=host1,host2
#quartz table prefixes in the database
org.quartz.jobStore.collectionPrefix=quartz_
org.quartz.threadPool.threadCount = 4
Can anyone recommend either a way to back Quartz with MongoDB use quartz.properties, or a simple alternative to Quartz?
Use this method for get scheduler with/without properties
public Scheduler getScheduler(Properties properties) {
SchedulerFactory factory;
if (!properties.isEmpty()) {
// with properties
factory = new StdSchedulerFactory(properties);
} else {
// without properties
factory = new StdSchedulerFactory();
}
return factory.getScheduler();
}
And this method for load properties file
public Scheduler load() throws SchedulerException {
Properties prop = new Properties();
try {
// file 'quartz.properties' in the 'src/main/resources/config' (Maven project structure)
properties.load(this.getClass().getResourceAsStream("/config/my-quartz.properties"));
} catch (IOException e) {
// process the exception, maybe load default properties
}
return getScheduler(properties);
}
You can put properties file into 'src/main/resources/config' folder,
or set $JAVA_OPTS=-Dorg.quartz.properties=/config/my-quartz.properties
Also you can load properties with Spring
#Component
public class SchedulerLoader {
#Value("${org.quartz.jobStore.class}")
private String quartzJobStoreClass;
#Value("${org.quartz.jobStore.mongoUri}")
private String quartzJobStoreMongoUri;
#Value("${org.quartz.jobStore.dbName}")
private String quartzJobStoreDbName;
#Value("${org.quartz.jobStore.collectionPrefix}")
private String quartzJobStoreCollectionPrefix;
#Value("${org.quartz.threadPool.threadCount}")
private String quartzThreadPoolThreadCount;
#Value("${org.quartz.jobStore.addresses}")
private String quartzJobStoreAddresses;
public Scheduler load() throws SchedulerException {
Properties properties = new Properties();
try {
properties.setProperty("org.quartz.jobStore.class", quartzJobStoreClass);
properties.setProperty("org.quartz.jobStore.mongoUri", quartzJobStoreMongoUri);
properties.setProperty("org.quartz.jobStore.dbName", quartzJobStoreDbName);
properties.setProperty("org.quartz.jobStore.collectionPrefix", quartzJobStoreCollectionPrefix);
properties.setProperty("org.quartz.threadPool.threadCount", quartzThreadPoolThreadCount);
properties.setProperty("org.quartz.jobStore.addresses", quartzJobStoreAddresses);
} catch (IOException e) {
// process the exception, maybe load default properties
}
return getScheduler(properties);
}
...
with Spring config
<beans ...>
...
<context:annotation-config/>
<context:property-placeholder location="classpath:config/*.properties"/>
...
There are properties file
# Use the MongoDB store
org.quartz.jobStore.class=com.novemberain.quartz.mongodb.MongoDBJobStore
# MongoDB URI (optional if 'org.quartz.jobStore.addresses' is set)
org.quartz.jobStore.mongoUri=mongodb://localhost:27020
# comma separated list of mongodb hosts/replica set seeds (optional if 'org.quartz.jobStore.mongoUri' is set)
org.quartz.jobStore.addresses=host1,host2
# database name
org.quartz.jobStore.dbName=quartz
# Will be used to create collections like mycol_jobs, mycol_triggers, mycol_calendars, mycol_locks
org.quartz.jobStore.collectionPrefix=mycol
# thread count setting is ignored by the MongoDB store but Quartz requries it
org.quartz.threadPool.threadCount=1
Also you should add Maven dependency (check https://github.com/michaelklishin/quartz-mongodb for details)
<dependency>
<groupId>com.novemberain</groupId>
<artifactId>quartz-mongodb</artifactId>
<version>2.0.0-rc1</version>
</dependency>

Categories