Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Add test file for script to generate random results when creating large courses locally #9298

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions supporting_scripts/course-scripts/quick-course-setup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@ The script will automatically perform all the necessary steps:
5. Create a programming exercise or use an existing one.
6. Add participation and commit for each student.

### Optional: Generating Different Results For All Created Students (Should only be done Locally!!)

If you want to generate different results for all the students created by the script:

1. Navigate to the [testFiles](../../../src/main/resources/templates/java/test/testFiles) folder and copy the [RandomizedTestCases](./testFiles-template/randomized/RandomizedTestCases.java) file into it.
If you want, you can delete the existing folders (behavior and structural) from the programming exercise’s test case template. The new test cases will randomly pass or fail, causing different results for each student.
2. Rebuild Artemis to apply the changes.
3. Run the main method in large_course_main.py. Now, all created students should have varying results in the programming exercise.
```shell
python3 large_course_main.py
```
4. Make sure to revert these changes after running the script. You can copy the original test case files from the [default](./testFiles-template/default) folder back into the [testFiles](../../../src/main/resources/templates/java/test/testFiles) folder and delete the [RandomizedTestCases](./testFiles-template/randomized/RandomizedTestCases.java) file that was copied to [testFiles](../../../src/main/resources/templates/java/test/testFiles) in Step 1.
az108 marked this conversation as resolved.
Show resolved Hide resolved
Otherwise, you risk breaking the real template of the programming exercise if these changes are pushed.

### Optional: Using an Existing Programming Exercise (Can also be done on Test Server)
az108 marked this conversation as resolved.
Show resolved Hide resolved
Alternatively, you can use an existing programming exercise and push the [RandomizedTestCases](./testFiles-template/randomized/RandomizedTestCases.java) file to the test repository of the programming exercise.
Make sure to adjust the [config.ini](./config.ini) file to use the existing programming exercise with the corresponding exercise ID, allowing the script to push with the created students to this existing programming exercise.

az108 marked this conversation as resolved.
Show resolved Hide resolved
### Optional: Deleting All Created Students

If you want to delete all the students created by the script:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package ${packageName};

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

import java.lang.reflect.InvocationTargetException;
import java.text.*;
import java.util.*;

import static de.tum.in.test.api.util.ReflectionTestUtils.*;

import de.tum.in.test.api.BlacklistPath;
import de.tum.in.test.api.PathType;
import de.tum.in.test.api.StrictTimeout;
import de.tum.in.test.api.WhitelistPath;
import de.tum.in.test.api.jupiter.Public;

/**
* @author Stephan Krusche ([email protected])
* @version 5.1 (11.06.2021)
*/
@Public
@WhitelistPath("target") // mainly for Artemis
@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
class SortingExampleBehaviorTest {

private List<Date> dates;
private List<Date> datesWithCorrectOrder;

@BeforeEach
void setup() throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
Date date1 = dateFormat.parse("08.11.2018");
Date date2 = dateFormat.parse("15.04.2017");
Date date3 = dateFormat.parse("15.02.2016");
Date date4 = dateFormat.parse("15.09.2017");

this.dates = Arrays.asList(date1, date2, date3, date4);
this.datesWithCorrectOrder = Arrays.asList(date3, date2, date4, date1);
}

@Test
@StrictTimeout(1)
void testBubbleSort() {
BubbleSort bubbleSort = new BubbleSort();
bubbleSort.performSort(dates);
if (!datesWithCorrectOrder.equals(dates)) {
fail("BubbleSort does not sort correctly");
}
}

@Test
@StrictTimeout(1)
void testMergeSort() {
MergeSort mergeSort = new MergeSort();
mergeSort.performSort(dates);
if (!datesWithCorrectOrder.equals(dates)) {
fail("MergeSort does not sort correctly");
}
}

@Test
@StrictTimeout(1)
void testUseMergeSortForBigList() throws ReflectiveOperationException {
List<Date> bigList = new ArrayList<Date>();
for (int i = 0; i < 11; i++) {
bigList.add(new Date());
}
Object chosenSortStrategy = configurePolicyAndContext(bigList);
if (!(chosenSortStrategy instanceof MergeSort)) {
fail("The sort algorithm of Context was not MergeSort for a list with more than 10 dates.");
}
}

@Test
@StrictTimeout(1)
void testUseBubbleSortForSmallList() throws ReflectiveOperationException {
List<Date> smallList = new ArrayList<Date>();
for (int i = 0; i < 3; i++) {
smallList.add(new Date());
}
Object chosenSortStrategy = configurePolicyAndContext(smallList);
if (!(chosenSortStrategy instanceof BubbleSort)) {
fail("The sort algorithm of Context was not BubbleSort for a list with less or equal than 10 dates.");
}
}

private Object configurePolicyAndContext(List<Date> dates) throws ReflectiveOperationException {
Object context = newInstance("${packageName}.Context");
invokeMethod(context, getMethod(context, "setDates", List.class), dates);

Object policy = newInstance("${packageName}.Policy", context);
invokeMethod(policy, getMethod(policy, "configure"));

Object chosenSortStrategy = invokeMethod(context, getMethod(context, "getSortAlgorithm"));
return chosenSortStrategy;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ${packageName};

import java.net.URISyntaxException;

import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.TestFactory;

import de.tum.in.test.api.BlacklistPath;
import de.tum.in.test.api.PathType;
import de.tum.in.test.api.StrictTimeout;
import de.tum.in.test.api.WhitelistPath;
import de.tum.in.test.api.jupiter.Public;
import de.tum.in.test.api.structural.AttributeTestProvider;

/**
* @author Stephan Krusche ([email protected])
* @version 5.1 (11.06.2021)
* <br><br>
* This test evaluates if the specified attributes in the structure oracle are correctly implemented with the expected type, visibility modifiers and annotations,
* based on its definition in the structure oracle (test.json).
*/
@Public
@WhitelistPath("target") // mainly for Artemis
@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
class AttributeTest extends AttributeTestProvider {

/**
* This method collects the classes in the structure oracle file for which attributes are specified.
* These classes are then transformed into JUnit 5 dynamic tests.
* @return A dynamic test container containing the test for each class which is then executed by JUnit.
*/
@Override
@StrictTimeout(10)
@TestFactory
protected DynamicContainer generateTestsForAllClasses() throws URISyntaxException {
structureOracleJSON = retrieveStructureOracleJSON(this.getClass().getResource("test.json"));
return super.generateTestsForAllClasses();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ${packageName};

import java.net.URISyntaxException;

import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.TestFactory;

import de.tum.in.test.api.BlacklistPath;
import de.tum.in.test.api.PathType;
import de.tum.in.test.api.StrictTimeout;
import de.tum.in.test.api.WhitelistPath;
import de.tum.in.test.api.jupiter.Public;
import de.tum.in.test.api.structural.ClassTestProvider;

/**
* @author Stephan Krusche ([email protected])
* @version 5.1 (11.06.2021)
* <br><br>
* This test evaluates the hierarchy of the class, i.e. if the class is abstract or an interface or an enum and also if the class extends another superclass and if
* it implements the interfaces and annotations, based on its definition in the structure oracle (test.json).
*/
@Public
@WhitelistPath("target") // mainly for Artemis
@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
class ClassTest extends ClassTestProvider {

/**
* This method collects the classes in the structure oracle file for which at least one class property is specified.
* These classes are then transformed into JUnit 5 dynamic tests.
* @return A dynamic test container containing the test for each class which is then executed by JUnit.
*/
@Override
@StrictTimeout(10)
@TestFactory
protected DynamicContainer generateTestsForAllClasses() throws URISyntaxException {
structureOracleJSON = retrieveStructureOracleJSON(this.getClass().getResource("test.json"));
return super.generateTestsForAllClasses();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ${packageName};

import java.net.URISyntaxException;

import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.TestFactory;

import de.tum.in.test.api.BlacklistPath;
import de.tum.in.test.api.PathType;
import de.tum.in.test.api.StrictTimeout;
import de.tum.in.test.api.WhitelistPath;
import de.tum.in.test.api.jupiter.Public;
import de.tum.in.test.api.structural.ConstructorTestProvider;

/**
* @author Stephan Krusche ([email protected])
* @version 5.1 (11.06.2021)
* <br><br>
* This test evaluates if the specified constructors in the structure oracle are correctly implemented with the expected parameter types and annotations,
* based on its definition in the structure oracle (test.json).
*/
@Public
@WhitelistPath("target") // mainly for Artemis
@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
class ConstructorTest extends ConstructorTestProvider {

/**
* This method collects the classes in the structure oracle file for which constructors are specified.
* These classes are then transformed into JUnit 5 dynamic tests.
* @return A dynamic test container containing the test for each class which is then executed by JUnit.
*/
@Override
@StrictTimeout(10)
@TestFactory
protected DynamicContainer generateTestsForAllClasses() throws URISyntaxException {
structureOracleJSON = retrieveStructureOracleJSON(this.getClass().getResource("test.json"));
return super.generateTestsForAllClasses();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ${packageName};

import java.net.URISyntaxException;

import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.TestFactory;

import de.tum.in.test.api.BlacklistPath;
import de.tum.in.test.api.PathType;
import de.tum.in.test.api.StrictTimeout;
import de.tum.in.test.api.WhitelistPath;
import de.tum.in.test.api.jupiter.Public;
import de.tum.in.test.api.structural.MethodTestProvider;

/**
* @author Stephan Krusche ([email protected])
* @version 5.1 (11.06.2021)
* <br><br>
* This test evaluates if the specified methods in the structure oracle are correctly implemented with the expected name, return type, parameter types, visibility modifiers
* and annotations, based on its definition in the structure oracle (test.json)
*/
@Public
@WhitelistPath("target") // mainly for Artemis
@BlacklistPath("target/test-classes") // prevent access to test-related classes and resources
class MethodTest extends MethodTestProvider {

/**
* This method collects the classes in the structure oracle file for which methods are specified.
* These classes are then transformed into JUnit 5 dynamic tests.
* @return A dynamic test container containing the test for each class which is then executed by JUnit.
*/
@Override
@StrictTimeout(10)
@TestFactory
protected DynamicContainer generateTestsForAllClasses() throws URISyntaxException {
structureOracleJSON = retrieveStructureOracleJSON(this.getClass().getResource("test.json"));
return super.generateTestsForAllClasses();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[ {
"class" : {
"name" : "MergeSort",
"package" : "${packageName}",
"interfaces" : [ "SortStrategy" ]
}
}, {
"class" : {
"name" : "Context",
"package" : "${packageName}"
},
"methods" : [ {
"name" : "getDates",
"modifiers" : [ "public" ],
"returnType" : "List<Date>"
}, {
"name" : "setDates",
"modifiers" : [ "public" ],
"parameters" : [ "List" ],
"returnType" : "void"
}, {
"name" : "setSortAlgorithm",
"modifiers" : [ "public" ],
"parameters" : [ "SortStrategy" ],
"returnType" : "void"
}, {
"name" : "getSortAlgorithm",
"modifiers" : [ "public" ],
"returnType" : "SortStrategy"
}, {
"name" : "sort",
"modifiers" : [ "public" ],
"returnType" : "void"
} ],
"attributes" : [ {
"name" : "sortAlgorithm",
"modifiers" : [ "private" ],
"type" : "SortStrategy"
}, {
"name" : "dates",
"modifiers" : [ "private" ],
"type" : "List<Date>"
} ]
}, {
"class" : {
"name" : "Policy",
"package" : "${packageName}"
},
"methods" : [ {
"name" : "configure",
"modifiers" : [ "public" ],
"returnType" : "void"
} ],
"attributes" : [ {
"name" : "context",
"modifiers" : [ "private", "optional: final" ],
"type" : "Context"
} ],
"constructors" : [ {
"modifiers" : [ "public" ],
"parameters" : [ "Context" ]
} ]
}, {
"class" : {
"name" : "SortStrategy",
"package" : "${packageName}",
"isInterface" : true
},
"methods" : [ {
"name" : "performSort",
"modifiers" : [ "public", "abstract" ],
"parameters" : [ "List" ],
"returnType" : "void"
} ]
}, {
"class" : {
"name" : "BubbleSort",
"package" : "${packageName}",
"interfaces" : [ "SortStrategy" ]
}
} ]
Loading
Loading