atg.test.AtgDustCase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of atgdust Show documentation
Show all versions of atgdust Show documentation
ATG DUST is a framework for building JUnit tests for
applications built on the ATG Dynamo platform. This framework allows
one to quickly write test code that depends up Nucleus or ATG
Repositories. By using this framework one can drastically cut down
on development time. It takes only a few seconds to start up a test
with a repository, but it may take multiple minutes to start up an
application server. To get started with DUST, take a look at
http://atgdust.sourceforge.net/first-test.html. This page will walk
you through the process of running a basic test which starts
Nucleus. After that, read the other getting started guides to
describe how to create standalone Junit tests which can startup
repositories and use the DynamoHttpServletResponse classes.
For only ATG10 and tested.
The newest version!
package atg.test;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import junit.framework.TestCase;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import atg.nucleus.GenericService;
import atg.nucleus.Nucleus;
import atg.nucleus.logging.ClassLoggingFactory;
import atg.nucleus.logging.ConsoleLogListener;
import atg.test.configuration.BasicConfiguration;
import atg.test.configuration.RepositoryConfiguration;
import atg.test.util.FileUtil;
import atg.test.util.RepositoryManager;
/**
* Replacement base class for {@link AtgDustTestCase}. Extend this class and use
* the following 'pattern' whenever you want to junit test some atg components:
*
* - Copy all needed configuration and repository mapping files to a
* staging location outside of your source tree using
* {@link AtgDustCase#copyConfigurationFiles(String[], String, String...)}.
* The staging directory will automatically be used as the configuration
* directory. Copying all needed priorities to a location outside of the source
* tree is the preferred method, because this frameworks creates properties on
* the fly and that could pollute your current source tree.
*
*
*
*
*
* Repository based tests are depended on one of the two steps previously
* described plus:
*
* - {@link AtgDustCase#prepareRepository(String, String...)} for
* testing against an default in-memory hsql database or
* {@link AtgDustCase#prepareRepository(String, Properties, boolean, String...)}
* for testing against an existing database.
*
*
* If you need to generate some components "on the fly":
*
* - {@link AtgDustCase#createPropertyFile(String, String, Class)}
*
*
*
* Example usage can be found in test.SongsRepositoryTest.
*
*
*
* This class overrides Junit 3 and not Junit 4 because currently Junit 4 has
* some test runner/eclipse related bugs which makes it impossible for me to use
* it.
*
*
* @author robert
*/
@SuppressWarnings("unchecked")
public class AtgDustCase extends TestCase {
private static final Logger log = Logger.getLogger(AtgDustCase.class);
private RepositoryManager repositoryManager = new RepositoryManager();
private final BasicConfiguration basicConfiguration = new BasicConfiguration();
private File configurationLocation;
private Nucleus nucleus;
private boolean isDebug;
private String atgConfigPath;
private String environment;
private String localConfig;
private List configDstsDir;
private static Map CONFIG_FILES_TIMESTAMPS,
CONFIG_FILES_GLOBAL_FORCE = null;
private static Class> perflib;
public static final File TIMESTAMP_SER = new File(System
.getProperty("java.io.tmpdir")
+ File.separator + "atg-dust-tstamp-rh.ser"),
GLOBAL_FORCE_SER = new File(System.getProperty("java.io.tmpdir")
+ File.separator + "atg-dust-gforce-rh.ser");
private static long SERIAL_TTL = 43200000L;
/**
* Every *.properties file copied using this method will have it's scope (if
* one is available) set to global.
*
* @param srcDirs
* One or more directories containing needed configuration files.
* @param dstDir
* where to copy the above files to. This will also be the
* configuration location.
* @param excludes
* One or more directories not to include during the copy
* process. Use this one to speeds up the test cycle
* considerably. You can also call it with an empty
* {@link String[]} or null
if nothing should be
* excluded
* @throws IOException
* Whenever some file related error's occur.
*/
protected final void copyConfigurationFiles(final String[] srcDirs,
final String dstDir, final String... excludes) throws IOException {
setConfigurationLocation(dstDir);
if (log.isDebugEnabled()) {
log.debug("Copying configuration files and "
+ "forcing global scope on all configs");
}
preCopyingOfConfigurationFiles(srcDirs, excludes);
for (final String srcs : srcDirs) {
FileUtil.copyDirectory(srcs, dstDir, Arrays
.asList(excludes == null ? new String[] {} : excludes));
}
forceGlobalScopeOnAllConfigs(dstDir);
if (FileUtil.isDirty()) {
FileUtil.serialize(GLOBAL_FORCE_SER, FileUtil
.getConfigFilesTimestamps());
}
}
/**
* Donated by Remi Dupuis
*
* @param properties
* @throws IOException
*/
protected final void manageConfigurationFiles(Properties properties)
throws IOException {
String atgConfigPath = properties.getProperty("atgConfigsJars")
.replace("/", File.separator);
String[] configs = properties.getProperty("configs").split(",");
String environment = properties.getProperty("environment");
String localConfig = properties.getProperty("localConfig");
String[] excludes = properties.getProperty("excludes").split(",");
String rootConfigDir = properties.getProperty("rootConfigDir").replace(
"/", File.separator);
int i = 0;
for (String conf : configs) {
String src = conf.split(" to ")[0];
String dst = conf.split(" to ")[1];
configs[i] = (rootConfigDir + "/" + src.trim() + " to "
+ rootConfigDir + "/" + dst.trim()).replace("/",
File.separator);
i++;
}
i = 0;
for (String dir : excludes) {
excludes[i] = dir.trim();
i++;
}
final List srcsAsList = new ArrayList();
final List distsAsList = new ArrayList();
for (String config : configs) {
srcsAsList.add(config.split(" to ")[0]);
distsAsList.add(config.split(" to ")[1]);
}
this.atgConfigPath = atgConfigPath;
this.environment = environment;
this.localConfig = localConfig;
// The Last dstdir is used for Configuration location
setConfigurationLocation(distsAsList.get(distsAsList.size() - 1));
if (log.isDebugEnabled()) {
log.debug("Copying configuration files and "
+ "forcing global scope on all configs");
}
preCopyingOfConfigurationFiles(srcsAsList.toArray(new String[] {}),
excludes);
log.info("Copying configuration files and "
+ "forcing global scope on all configs");
// copy all files to it's destination
for (String config : configs) {
FileUtil.copyDirectory(config.split(" to ")[0], config
.split(" to ")[1], Arrays
.asList(excludes == null ? new String[] {} : excludes));
log.debug(config);
log.debug(config.split(" to ")[0]);
log.debug(config.split(" to ")[1]);
}
// forcing global scope on all configurations
for (String config : configs) {
String dstDir = config.split(" to ")[1];
// forcing global scope on all property files
forceGlobalScopeOnAllConfigs(dstDir);
}
this.configDstsDir = distsAsList;
}
/**
* @param configurationStagingLocation
* The location where the property file should be created. This
* will also set the {@link AtgDustCase#configurationLocation}.
*
* @param nucleusComponentPath
* Nucleus component path (e.g /Some/Service/Impl).
*
* @param clazz
* The {@link Class} implementing the nucleus component specified
* in previous argument.
*
* @throws IOException
* If we have some File related errors
*/
protected final void createPropertyFile(
final String configurationStagingLocation,
final String nucleusComponentPath, final Class> clazz)
throws IOException {
this.configurationLocation = new File(configurationStagingLocation);
FileUtil.createPropertyFile(nucleusComponentPath,
configurationLocation, clazz.getClass(),
new HashMap());
}
/**
* Prepares a test against an default in-memory hsql database.
*
* @param repoPath
* the nucleus component path of the repository to be tested.
*
* @param definitionFiles
* one or more repository definition files.
* @throws IOException
* The moment we have some properties/configuration related
* error
* @throws SQLException
* Whenever there is a database related error
*
*/
protected final void prepareRepository(final String repoPath,
final String... definitionFiles) throws SQLException, IOException {
final Properties properties = new Properties();
properties.put("driver", "org.hsqldb.jdbcDriver");
properties.put("url", "jdbc:hsqldb:mem:testDb");
properties.put("user", "sa");
properties.put("password", "");
prepareRepository(repoPath, properties, true, true, definitionFiles);
}
/**
* Prepares a test against an existing database.
*
* @param repositoryPath
* The the repository to be tested, specified as nucleus
* component path.
* @param connectionProperties
* A {@link Properties} instance with the following values (in
* this example the properties are geared towards an mysql
* database):
*
*
* final Properties properties = new Properties();
* properties.put("driver", "com.mysql.jdbc.Driver");
* properties.put("url", "jdbc:mysql://localhost:3306/someDb");
* properties.put("user", "someUserName");
* properties.put("password", "somePassword");
*
*
*
* @param dropTables
* If true
then existing tables will be dropped and
* re-created, if set to false
the existing tables
* will be used.
*
* @param createTables
* if set to true
all non existing tables needed for
* the current test run will be created, if set to
* false
this class expects all needed tables for
* this test run to be already created
*
* @param definitionFiles
* One or more needed repository definition files.
* @throws IOException
* The moment we have some properties/configuration related
* error
* @throws SQLException
* Whenever there is a database related error
*
*/
protected final void prepareRepository(final String repositoryPath,
final Properties connectionProperties, final boolean dropTables,
final boolean createTables, final String... definitionFiles)
throws SQLException, IOException {
final Map connectionSettings = new HashMap();
for (final Iterator> it = connectionProperties
.entrySet().iterator(); it.hasNext();) {
final Entry