All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.continuous.ContinuousTestGeneration Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/**
 * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.continuous;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.evosuite.Properties;
import org.evosuite.continuous.job.JobDefinition;
import org.evosuite.continuous.job.JobExecutor;
import org.evosuite.continuous.job.JobScheduler;
import org.evosuite.continuous.persistency.StorageManager;
import org.evosuite.continuous.project.ProjectAnalyzer;
import org.evosuite.continuous.project.ProjectStaticData;
import org.evosuite.utils.FileIOUtils;
import org.evosuite.xsd.Project;
import org.evosuite.xsd.ProjectUtil;


/**
 * 

* This is the main entry point for the new * paradigm "Continuous Test Generation" (CTG). * This can be called directly from EvoSuite for * experiment reasons, but its usage for practitioners * will be based on build environments like Maven/Ant * and continuous integration environments like * Jenkins/Hudson/Bamboo *

* *

* In a nutshell, the idea is for a project to keep track/store * the best test suite for each class in the project. * Each time CTG is run (and can be run continuously), we try * to generate test suites for classes we haven't addressed * yet, and we try to improve the current ones (by seeding). * Benefits are for example: *

    *
  • No need to download EvoSuite. This is done automatically * with Maven
  • *
  • Smart allocation of search budget among classes with * different size/difficulty
  • *
  • Very easily configurable to run 24/7, with reports on entire * project
  • *
  • Possibility to reuse test cases/data from one class to * help generation of test suites for new classes
  • *
  • Can automatically check from repository which classes * have been modified, and concentrate search on them
  • *
*

* *

* CTG can also be configured to "call home". * This will be useful to see how EvoSuite is used in practice. *

* * *

* TODO we should also have an option "regression" to run * current test suites, and see if any fails. * Even if do not want to explicitly do regression, we might still * have to run old test cases, as failing ones should be (re)moved and * labelled as "regression-failing" * * *

* TODO need also option to automatically commit to repository any new, better test * * @author arcuri * */ public class ContinuousTestGeneration { /** * Target folder/jar defining the SUT */ private final String target; /** * Defines what classes in the target should be used by specifying * a common package prefix */ private final String prefix; /** * The complete, used classpath */ private final String projectClassPath; private CtgConfiguration configuration; /** * An optional folder where to make a copy of the generated tests */ private final String exportFolder; /** * Specify which CUT to use. If {@code null} then use everything in target/prefix */ private String[] cuts; public ContinuousTestGeneration(String target, String projectClassPath, String prefix, CtgConfiguration conf, String[] cuts, String exportFolder) { super(); this.target = target; this.prefix = prefix; this.projectClassPath = projectClassPath; this.configuration = conf; this.cuts = cuts; this.exportFolder = exportFolder; } /** * Apply CTG, and return a string with some summary * * @return */ public String execute() { //init the local storage manager StorageManager storage = new StorageManager(); if (!storage.isStorageOk()) { return "Failed to initialize local storage system"; } if(Properties.CTG_DELETE_OLD_TMP_FOLDERS){ storage.deleteAllOldTmpFolders(); } if (!storage.createNewTmpFolders()) { return "Failed to create tmp folders"; } //check project ProjectAnalyzer analyzer = new ProjectAnalyzer(target, prefix, cuts); ProjectStaticData data = analyzer.analyze(); if (data.getTotalNumberOfTestableCUTs() == 0) { return "There is no class to test in the chosen project\n" + "Target: " + target + "\n" + "Prefix: '" + prefix + "'\n"; } if(Properties.CTG_DEBUG_PORT != null && data.getTotalNumberOfTestableCUTs() != 1){ throw new IllegalStateException("Cannot debug CTG when more than one CUT is selected"); } if (Properties.CTG_TIME_PER_CLASS != null) { configuration = configuration.getWithChangedTime(Properties.CTG_TIME_PER_CLASS, data.getTotalNumberOfTestableCUTs()); } JobScheduler scheduler = new JobScheduler(data, configuration); JobExecutor executor = new JobExecutor(storage, projectClassPath, configuration); //loop: define (partial) schedule while (scheduler.canExecuteMore()) { List jobs = scheduler.createNewSchedule(); executor.executeJobs(jobs, configuration.getNumberOfUsableCores()); executor.waitForJobs(); } String description = storage.mergeAndCommitChanges(data, cuts); if(exportFolder != null){ try { exportToFolder(".",exportFolder); } catch (IOException e) { return "Failed to export tests: "+e.getMessage(); } } //call home if (configuration.callHome) { //TODO } return description; } public static File resolveExportFolder(String baseFolder, String exportFolder){ Path exp = Paths.get(exportFolder); if(exp.isAbsolute()){ return exp.toFile(); } else { return Paths.get(baseFolder,exportFolder).toAbsolutePath().toFile(); } } public static boolean exportToFolder(String baseFolder, String exportFolder) throws IOException { File basedir = new File(baseFolder); File evoFolder = StorageManager.getBestTestFolder(basedir); File[] children = evoFolder.listFiles(); boolean isEmpty = children==null || children.length==0; if(isEmpty){ return false; } File target = resolveExportFolder(baseFolder, exportFolder); //FileUtils.copyDirectory(evoFolder, target); //This did not overwrite old files! FileIOUtils.copyDirectoryAndOverwriteFilesIfNeeded(evoFolder,target); return true; } /** * Clean all persistent data (eg files on disk) that * CTG has created so far */ public boolean clean(){ StorageManager storage = new StorageManager(); return storage.clean(); } /** * Get info on the current test cases in the database * @return */ public String info(){ Project project = StorageManager.getDatabaseProject(); if(project==null){ return "No info available"; } //TODO all info StringBuilder sb = new StringBuilder(); sb.append("Total number of classes in the project: "+ ProjectUtil.getNumberTestableClasses(project)+"\n"); sb.append("Number of classes in the project that are testable: "+ ProjectUtil.getNumberTestableClasses(project)+"\n"); sb.append("Number of generated test suites: "+ ProjectUtil.getNumberGeneratedTestSuites(project)+"\n"); sb.append("Overall coverage: "+ ProjectUtil.getOverallCoverage(project)+"\n"); return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy