WIP: Improve test data creation #112

Draft
ansv7779 wants to merge 4 commits from test-data-improvements into develop
12 changed files with 152 additions and 7 deletions

View File

@ -1017,11 +1017,6 @@ public class CoreConfig {
); );
} }
@Bean
public DataInitializer dataInitializer() {
return new DataInitializer();
}
@Bean @Bean
public FinalSeminarActivityHandler finalSeminarActivityHandler( public FinalSeminarActivityHandler finalSeminarActivityHandler(
ActivityPlanFacade activityPlanFacade, ActivityPlanFacade activityPlanFacade,

View File

@ -15,6 +15,7 @@
<module>daisy-integration</module> <module>daisy-integration</module>
<module>war</module> <module>war</module>
<module>api</module> <module>api</module>
<module>test-data</module>
</modules> </modules>
<properties> <properties>

20
test-data/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>se.su.dsv.scipro</groupId>
<artifactId>SciPro</artifactId>
<version>0.1-SNAPSHOT</version>
</parent>
<artifactId>test-data</artifactId>
<dependencies>
<dependency>
<groupId>se.su.dsv.scipro</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,19 @@
package se.su.dsv.scipro.testdata;
import se.su.dsv.scipro.system.ProjectType;
/// All the base test data that can be re-used in different test cases.
///
/// **Do not modify any of this data.** There are many
/// [TestDataPopulator]s that rely on this data to be in a specific state.
///
/// In addition to the data that is available here there is also much additional
/// data that has been created;
///
/// - A grading report template for each [ProjectType]
///
public interface BaseData {
ProjectType bachelor();
ProjectType magister();
ProjectType master();
}

View File

@ -1,4 +1,4 @@
package se.su.dsv.scipro; package se.su.dsv.scipro.testdata;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.inject.Provider; import jakarta.inject.Provider;
@ -32,13 +32,16 @@ import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.*; import se.su.dsv.scipro.system.*;
import se.su.dsv.scipro.util.Pair; import se.su.dsv.scipro.util.Pair;
public class DataInitializer implements Lifecycle { public class DataInitializer implements Lifecycle, BaseData, Factory {
public static final int APPLICATION_PERIOD_START_MINUS_DAYS = 1; public static final int APPLICATION_PERIOD_START_MINUS_DAYS = 1;
public static final int APPLICATION_PERIOD_END_PLUS_DAYS = 3; public static final int APPLICATION_PERIOD_END_PLUS_DAYS = 3;
public static final int APPLICATION_PERIOD_COURSE_START_PLUS_DAYS = 5; public static final int APPLICATION_PERIOD_COURSE_START_PLUS_DAYS = 5;
public static final long RESEARCH_AREA_ID = 12L; public static final long RESEARCH_AREA_ID = 12L;
@Inject
private Collection<TestDataPopulator> testDataPopulators = new ArrayList<>();
@Inject @Inject
private UserService userService; private UserService userService;
@ -101,6 +104,9 @@ public class DataInitializer implements Lifecycle {
@Override @Override
public void start() { public void start() {
if (profile.getCurrentProfile() == Profiles.DEV && noUsers()) { if (profile.getCurrentProfile() == Profiles.DEV && noUsers()) {
for (TestDataPopulator testDataPopulator : testDataPopulators) {
testDataPopulator.populate(this, this);
}
createDefaultProjectTypesIfNotDone(); createDefaultProjectTypesIfNotDone();
createDefaultChecklistCategoriesIfNotDone(); createDefaultChecklistCategoriesIfNotDone();
createApplicationPeriodIfNotDone(); createApplicationPeriodIfNotDone();
@ -1958,6 +1964,36 @@ public class DataInitializer implements Lifecycle {
return entity; return entity;
} }
@Override
public ProjectType bachelor() {
return bachelorClass;
}
@Override
public ProjectType magister() {
return magisterClass;
}
@Override
public ProjectType master() {
return masterClass;
}
@Override
public User createAuthor(String firstName) {
return createStudent(firstName);
}
@Override
public User createSupervisor(String firstName) {
return createEmployee(firstName);
}
@Override
public User createReviewer(String firstName) {
return createEmployee(firstName);
}
private static final class SimpleTextFile implements FileUpload { private static final class SimpleTextFile implements FileUpload {
private final User uploader; private final User uploader;

View File

@ -0,0 +1,12 @@
package se.su.dsv.scipro.testdata;
import se.su.dsv.scipro.system.User;
/**
* A factory to help with repetitive tasks when populating test data.
*/
public interface Factory {
User createAuthor(String firstName);
User createSupervisor(String firstName);
User createReviewer(String firstName);
}

View File

@ -0,0 +1,16 @@
package se.su.dsv.scipro.testdata;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import se.su.dsv.scipro.war.PluginConfiguration;
@Configuration(proxyBeanMethods = false)
@ComponentScan(basePackages = "se.su.dsv.scipro.testdata.populators")
public class TestDataConfiguration implements PluginConfiguration {
@Bean
public DataInitializer dataInitializer() {
return new DataInitializer();
}
}

View File

@ -0,0 +1,11 @@
package se.su.dsv.scipro.testdata;
public interface TestDataPopulator {
/**
* Add test data to the system to help with testing a specific feature.
*
* @param baseData the base data already populated
* @param factory helper object to make repetitive tasks easier (such as creating users)
*/
void populate(BaseData baseData, Factory factory);
}

View File

@ -0,0 +1,8 @@
/**
* This package contains the infrastructure that is used when generating test data for the application. To add new test
* data to the system, add a new class to the {@link se.su.dsv.scipro.testdata.populators} package that implements the
* {@link se.su.dsv.scipro.testdata.TestDataPopulator} interface and annotate it with
* {@link org.springframework.stereotype.Service @Service}. Inject dependencies as needed using
* {@link jakarta.inject.Inject @Inject}.
*/
package se.su.dsv.scipro.testdata;

View File

@ -0,0 +1,13 @@
/**
* Contains classes that populate the database with test data.
* <p>
* Prefer to use methods on the various services to create data, rather than directly interacting with the database
* using an {@link jakarta.persistence.EntityManager}. This is to make sure all business rules are enforced and that
* any additional logic is executed such as sending notifications or calculating statistics.
*
* @see se.su.dsv.scipro.testdata how to add new populators
* @see se.su.dsv.scipro.testdata.TestDataPopulator
* @see se.su.dsv.scipro.testdata.BaseData
* @see se.su.dsv.scipro.testdata.Factory
*/
package se.su.dsv.scipro.testdata.populators;

View File

@ -0,0 +1 @@
se.su.dsv.scipro.testdata.TestDataConfiguration

View File

@ -140,5 +140,18 @@
<spring.profile.active>branch</spring.profile.active> <spring.profile.active>branch</spring.profile.active>
</properties> </properties>
</profile> </profile>
<profile>
<id>DEV</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>se.su.dsv.scipro</groupId>
<artifactId>test-data</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</profile>
</profiles> </profiles>
</project> </project>