Skip to content
Snippets Groups Projects
Commit c70500d8 authored by srosse's avatar srosse
Browse files

OO-1593: remove conversion qti 1.2 to 2.1, onyx to qtiworks unit tests

parent ef353fd9
No related branches found
No related tags found
No related merge requests found
Showing
with 865 additions and 444 deletions
......@@ -30,9 +30,6 @@ import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.util.Util;
import org.olat.modules.portfolio.ui.PageRunController;
import org.olat.modules.portfolio.ui.editor.PageEditorController.EditorFragment;
import org.olat.modules.portfolio.ui.editor.event.AddElementEvent;
......
......@@ -19,21 +19,51 @@
*/
package org.olat.ims.qti21.model.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder.EntryType;
import org.olat.ims.qti21.model.xml.interactions.HotspotAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.MultipleChoiceAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.SingleChoiceAssessmentItemBuilder;
import uk.ac.ed.ph.jqtiplus.JqtiExtensionManager;
import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.ChoiceInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.ExtendedTextInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.HotspotInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.TextEntryInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleMatchSet;
import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
import uk.ac.ed.ph.jqtiplus.provision.BadResourceException;
import uk.ac.ed.ph.jqtiplus.reading.AssessmentObjectXmlLoader;
import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
import uk.ac.ed.ph.jqtiplus.validation.ItemValidationResult;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
/**
......@@ -42,17 +72,35 @@ import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@RunWith(Parameterized.class)
public class AssessmentItemBuilderTest {
private final JqtiExtensionManager jqtiExtensionManager = new JqtiExtensionManager();
private final QtiXmlReader qtiXmlReader = new QtiXmlReader(jqtiExtensionManager);
private final QtiSerializer qtiSerializer = new QtiSerializer(jqtiExtensionManager);
private static final OLog log = Tracing.createLoggerFor(AssessmentItemBuilderTest.class);
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ Boolean.TRUE },
{ Boolean.FALSE }
});
}
private Boolean build;
public AssessmentItemBuilderTest(Boolean build) {
this.build = build;
}
@Test
public void findFeedbacks() throws URISyntaxException {
URL itemUrl = AssessmentItemBuilderTest.class.getResource("assessment-item-single-choice-feedbacks.xml");
AssessmentItem assessmentItem = loadAssessmentItem(itemUrl);
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
SingleChoiceAssessmentItemBuilder itemBuilder = new SingleChoiceAssessmentItemBuilder(assessmentItem, qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
ModalFeedbackBuilder correctFeedback = itemBuilder.getCorrectFeedback();
Assert.assertNotNull(correctFeedback);
......@@ -61,10 +109,186 @@ public class AssessmentItemBuilderTest {
ModalFeedbackBuilder incorrectFeedback = itemBuilder.getIncorrectFeedback();
Assert.assertNotNull(incorrectFeedback);
Assert.assertTrue(incorrectFeedback.isIncorrectRule());
}
/**
* Check if a bare bone single choice created with our builder make a valid assessmentItem.
*
* @throws IOException
* @throws URISyntaxException
*/
@Test
public void buildAssessmentItem_singleChoice() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
SingleChoiceAssessmentItemBuilder itemBuilder = new SingleChoiceAssessmentItemBuilder(qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ChoiceInteraction);
}
/**
* Check if a bare bone multiple choice created with our builder make a valid assessmentItem.
*
* @throws IOException
* @throws URISyntaxException
*/
@Test
public void buildAssessmentItem_multipleChoice() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
MultipleChoiceAssessmentItemBuilder itemBuilder = new MultipleChoiceAssessmentItemBuilder(qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ChoiceInteraction);
}
@Test
public void buildAssessmentItem_essay() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
EssayAssessmentItemBuilder itemBuilder = new EssayAssessmentItemBuilder(qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ExtendedTextInteraction);
}
@Test
public void buildAssessmentItem_gap() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
FIBAssessmentItemBuilder itemBuilder = new FIBAssessmentItemBuilder(EntryType.text, qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof TextEntryInteraction);
TextEntryInteraction interaction = (TextEntryInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
}
@Test
public void buildAssessmentItem_hotspot() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
HotspotAssessmentItemBuilder itemBuilder = new HotspotAssessmentItemBuilder(qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof HotspotInteraction);
HotspotInteraction interaction = (HotspotInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
}
@Test
public void buildAssessmentItem_kprim() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
KPrimAssessmentItemBuilder itemBuilder = new KPrimAssessmentItemBuilder(qtiSerializer);
if(build.booleanValue()) {
itemBuilder.build();
}
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof MatchInteraction);
MatchInteraction interaction = (MatchInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
Assert.assertEquals(2, interaction.getSimpleMatchSets().size());
SimpleMatchSet matchSet = interaction.getSimpleMatchSets().get(0);
Assert.assertEquals(4, matchSet.getSimpleAssociableChoices().size());
SimpleMatchSet correctWrongSet = interaction.getSimpleMatchSets().get(1);
Assert.assertEquals(2, correctWrongSet.getSimpleAssociableChoices().size());
}
/**
* The method serialize as xml the assessmentItem, load it, validate it and return the itemResult.
*
* @param assessmentItem
* @return
* @throws IOException
*/
private ItemValidationResult serializeAndReload(AssessmentItem assessmentItem) throws IOException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
File tmpDir = new File(WebappHelper.getTmpDir(), "itembuilder" + UUID.randomUUID());
tmpDir.mkdirs();
File outputFile = new File(tmpDir, "sc_item.xml");
try(FileOutputStream out = new FileOutputStream(outputFile)) {
qtiSerializer.serializeJqtiObject(assessmentItem, out);
} catch(Exception e) {
log.error("", e);
}
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(outputFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
ItemValidationResult itemResult = assessmentObjectXmlLoader.loadResolveAndValidateItem(outputFile.toURI());
BadResourceException e = itemResult.getResolvedAssessmentItem().getItemLookup().getBadResourceException();
if(e != null) {
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
}
FileUtils.deleteDirsAndFiles(tmpDir.toPath());
Assert.assertFalse("Has errors", (itemResult.getModelValidationErrors().size() > 0));
return itemResult;
}
private AssessmentItem loadAssessmentItem(URL itemUrl) throws URISyntaxException {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(Paths.get(itemUrl.toURI()));
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
ResolvedAssessmentItem item = assessmentObjectXmlLoader.loadAndResolveAssessmentItem(itemUrl.toURI());
......
......@@ -19,45 +19,20 @@
*/
package org.olat.ims.qti21.model.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder.EntryType;
import org.olat.ims.qti21.model.xml.interactions.HotspotAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.MultipleChoiceAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.SingleChoiceAssessmentItemBuilder;
import uk.ac.ed.ph.jqtiplus.JqtiExtensionManager;
import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.ChoiceInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.ExtendedTextInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.HotspotInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.MatchInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.TextEntryInteraction;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.SimpleMatchSet;
import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
import uk.ac.ed.ph.jqtiplus.provision.BadResourceException;
import uk.ac.ed.ph.jqtiplus.reading.AssessmentObjectXmlLoader;
import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
import uk.ac.ed.ph.jqtiplus.validation.ItemValidationResult;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
/**
......@@ -68,8 +43,6 @@ import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
*/
public class AssessmentItemPackageTest {
private static final OLog log = Tracing.createLoggerFor(AssessmentItemPackageTest.class);
@Test
public void loadAssessmentItem() throws URISyntaxException {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
......@@ -86,176 +59,5 @@ public class AssessmentItemPackageTest {
Assert.assertNotNull(assessmentItem);
qtiSerializer.serializeJqtiObject(assessmentItem, System.out);
}
/**
* Check if a bare bone single choice created with our builder make a valid assessmentItem.
*
* @throws IOException
* @throws URISyntaxException
*/
@Test
public void buildAssessmentItem_singleChoice() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
SingleChoiceAssessmentItemBuilder itemBuilder = new SingleChoiceAssessmentItemBuilder(qtiSerializer);
itemBuilder.build();
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ChoiceInteraction);
}
/**
* Check if a bare bone multiple choice created with our builder make a valid assessmentItem.
*
* @throws IOException
* @throws URISyntaxException
*/
@Test
public void buildAssessmentItem_multipleChoice() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
MultipleChoiceAssessmentItemBuilder itemBuilder = new MultipleChoiceAssessmentItemBuilder(qtiSerializer);
itemBuilder.build();
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ChoiceInteraction);
}
@Test
public void buildAssessmentItem_essay() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
EssayAssessmentItemBuilder itemBuilder = new EssayAssessmentItemBuilder(qtiSerializer);
itemBuilder.build();
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof ExtendedTextInteraction);
}
@Test
public void buildAssessmentItem_gap() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
FIBAssessmentItemBuilder itemBuilder = new FIBAssessmentItemBuilder(EntryType.text, qtiSerializer);
itemBuilder.build();
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof TextEntryInteraction);
TextEntryInteraction interaction = (TextEntryInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
}
@Test
public void buildAssessmentItem_hotspot() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
HotspotAssessmentItemBuilder itemBuilder = new HotspotAssessmentItemBuilder(qtiSerializer);
itemBuilder.build();
AssessmentItem assessmentItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(assessmentItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof HotspotInteraction);
HotspotInteraction interaction = (HotspotInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
}
@Test
public void buildAssessmentItem_kprim() throws IOException, URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
KPrimAssessmentItemBuilder itemBuilder = new KPrimAssessmentItemBuilder(qtiSerializer);
itemBuilder.build();
AssessmentItem singleChoiceItem = itemBuilder.getAssessmentItem();
ItemValidationResult itemResult = serializeAndReload(singleChoiceItem);
AssessmentItem reloadedItem = itemResult.getResolvedAssessmentItem().getItemLookup().extractIfSuccessful();
List<Interaction> interactions = reloadedItem.getItemBody().findInteractions();
Assert.assertNotNull(interactions);
Assert.assertEquals(1, interactions.size());
Assert.assertTrue(interactions.get(0) instanceof MatchInteraction);
MatchInteraction interaction = (MatchInteraction)interactions.get(0);
Assert.assertNotNull(interaction.getResponseIdentifier());
ResponseDeclaration responseDeclaration = reloadedItem.getResponseDeclaration(interaction.getResponseIdentifier());
Assert.assertNotNull(responseDeclaration);
Assert.assertEquals(2, interaction.getSimpleMatchSets().size());
SimpleMatchSet matchSet = interaction.getSimpleMatchSets().get(0);
Assert.assertEquals(4, matchSet.getSimpleAssociableChoices().size());
SimpleMatchSet correctWrongSet = interaction.getSimpleMatchSets().get(1);
Assert.assertEquals(2, correctWrongSet.getSimpleAssociableChoices().size());
}
/**
* The method serialize as xml the assessmentItem, load it, validate it and return the itemResult.
*
* @param assessmentItem
* @return
* @throws IOException
*/
private ItemValidationResult serializeAndReload(AssessmentItem assessmentItem) throws IOException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
File tmpDir = Files.createTempDirectory("itembuilder").toFile();
if(!tmpDir.exists()) {
tmpDir.mkdirs();
}
File outputFile = new File(tmpDir, "sc_item.xml");
try(FileOutputStream out = new FileOutputStream(outputFile)) {
qtiSerializer.serializeJqtiObject(assessmentItem, out);
} catch(Exception e) {
log.error("", e);
}
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(outputFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
ItemValidationResult itemResult = assessmentObjectXmlLoader.loadResolveAndValidateItem(outputFile.toURI());
BadResourceException e = itemResult.getResolvedAssessmentItem().getItemLookup().getBadResourceException();
if(e != null) {
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
System.out.println(err);
}
FileUtils.deleteDirsAndFiles(tmpDir.toPath());
Assert.assertFalse("Has errors", (itemResult.getModelValidationErrors().size() > 0));
return itemResult;
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.ims.qti21.model.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import uk.ac.ed.ph.jqtiplus.JqtiExtensionManager;
import uk.ac.ed.ph.jqtiplus.node.content.variable.RubricBlock;
import uk.ac.ed.ph.jqtiplus.node.expression.operator.Sum;
import uk.ac.ed.ph.jqtiplus.node.expression.outcome.TestVariables;
import uk.ac.ed.ph.jqtiplus.node.outcome.declaration.OutcomeDeclaration;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentItemRef;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentSection;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
import uk.ac.ed.ph.jqtiplus.node.test.ItemSessionControl;
import uk.ac.ed.ph.jqtiplus.node.test.NavigationMode;
import uk.ac.ed.ph.jqtiplus.node.test.Ordering;
import uk.ac.ed.ph.jqtiplus.node.test.SubmissionMode;
import uk.ac.ed.ph.jqtiplus.node.test.TestFeedback;
import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
import uk.ac.ed.ph.jqtiplus.node.test.TimeLimits;
import uk.ac.ed.ph.jqtiplus.node.test.View;
import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.OutcomeProcessing;
import uk.ac.ed.ph.jqtiplus.node.test.outcome.processing.SetOutcomeValue;
import uk.ac.ed.ph.jqtiplus.notification.Notification;
import uk.ac.ed.ph.jqtiplus.provision.BadResourceException;
import uk.ac.ed.ph.jqtiplus.reading.AssessmentObjectXmlLoader;
import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.serialization.QtiSerializer;
import uk.ac.ed.ph.jqtiplus.types.Identifier;
import uk.ac.ed.ph.jqtiplus.validation.TestValidationResult;
import uk.ac.ed.ph.jqtiplus.value.BaseType;
import uk.ac.ed.ph.jqtiplus.value.Cardinality;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
/**
*
* Initial date: 04.06.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class AssessmentTestPackageTest {
private static final OLog log = Tracing.createLoggerFor(AssessmentTestPackageTest.class);
protected AssessmentTest createAssessmentTest(File itemFile) throws URISyntaxException {
AssessmentTest assessmentTest = new AssessmentTest();
assessmentTest.setIdentifier("id" + UUID.randomUUID());
assessmentTest.setTitle("My test");
assessmentTest.setToolName("OpenOLAT");
assessmentTest.setToolVersion("11.0");
//outcome declarations
OutcomeDeclaration scoreOutcomeDeclaration = new OutcomeDeclaration(assessmentTest);
scoreOutcomeDeclaration.setIdentifier(Identifier.parseString("SCORE"));
scoreOutcomeDeclaration.setCardinality(Cardinality.SINGLE);
scoreOutcomeDeclaration.setBaseType(BaseType.FLOAT);
assessmentTest.getOutcomeDeclarations().add(scoreOutcomeDeclaration);
//time limits
TimeLimits timeLimits = new TimeLimits(assessmentTest);
timeLimits.setAllowLateSubmission(Boolean.FALSE);
timeLimits.setMinimum(0.0d);
timeLimits.setMaximum(1800.0);
assessmentTest.setTimeLimits(timeLimits);
//test parts
TestPart part = new TestPart(assessmentTest);
part.setIdentifier(Identifier.parseString("id" + UUID.randomUUID()));
part.setNavigationMode(NavigationMode.NONLINEAR);
part.setSubmissionMode(SubmissionMode.INDIVIDUAL);
assessmentTest.getTestParts().add(part);
//part -> item session control
ItemSessionControl itemSessionControl = new ItemSessionControl(part);
itemSessionControl.setAllowComment(Boolean.TRUE);
itemSessionControl.setAllowReview(Boolean.TRUE);
itemSessionControl.setAllowSkipping(Boolean.TRUE);
itemSessionControl.setMaxAttempts(12);
itemSessionControl.setShowFeedback(Boolean.TRUE);
itemSessionControl.setShowSolution(Boolean.TRUE);
part.setItemSessionControl(itemSessionControl);
// section
AssessmentSection section = new AssessmentSection(part);
section.setFixed(Boolean.TRUE);
section.setVisible(Boolean.TRUE);
section.setTitle("My section");
section.setIdentifier(Identifier.parseString("id" + UUID.randomUUID()));
part.getAssessmentSections().add(section);
Ordering ordering = new Ordering(section);
ordering.setShuffle(false);
section.setOrdering(ordering);
RubricBlock rubrickBlock = new RubricBlock(section);
rubrickBlock.setViews(Collections.singletonList(View.CANDIDATE));
section.getRubricBlocks().add(rubrickBlock);
AssessmentItemRef item = new AssessmentItemRef(section);
item.setIdentifier(Identifier.parseString("id" + UUID.randomUUID()));
item.setHref(new URI(itemFile.getName()));
section.getSectionParts().add(item);
//outcome processing
OutcomeProcessing outcomeProcessing = new OutcomeProcessing(assessmentTest);
assessmentTest.setOutcomeProcessing(outcomeProcessing);
SetOutcomeValue outcomeRule = new SetOutcomeValue(outcomeProcessing);
outcomeRule.setIdentifier(Identifier.parseString("SCORE"));
Sum sum = new Sum(outcomeRule);
outcomeRule.getExpressions().add(sum);
TestVariables testVariables = new TestVariables(sum);
testVariables.setVariableIdentifier(Identifier.parseString("SCORE"));
sum.getExpressions().add(testVariables);
outcomeProcessing.getOutcomeRules().add(outcomeRule);
//feedbacks
List<TestFeedback> testFeedbacks = assessmentTest.getTestFeedbacks();
TestFeedback testFeedback = new TestFeedback(assessmentTest);
//testFeedback.
return assessmentTest;
}
@Test
public void buildAssessmentTest() throws URISyntaxException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
File fullPackage = new File("/Users/srosse/Desktop/QTI/Full/");
File itemFile = new File(fullPackage, "generated_item.xml");
AssessmentTest assessmentTest = createAssessmentTest(itemFile);
qtiSerializer.serializeJqtiObject(assessmentTest, System.out);
System.out.println("\n-------------");
File outputFile = new File("/Users/srosse/Desktop/QTI/generated_test.xml");
if(outputFile.exists()) {
outputFile.delete();
outputFile = new File("/Users/srosse/Desktop/QTI/generated_test.xml");
}
try(FileOutputStream out = new FileOutputStream(outputFile)) {
qtiSerializer.serializeJqtiObject(assessmentTest, out);
} catch(Exception e) {
log.error("", e);
}
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(outputFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
TestValidationResult test = assessmentObjectXmlLoader.loadResolveAndValidateTest(outputFile.toURI());
System.out.println("Has errors: " + (test.getModelValidationErrors().size() > 0));
for(Notification notification: test.getModelValidationErrors()) {
System.out.println(notification.getQtiNode() + " : " + notification.getMessage());
}
BadResourceException e = test.getResolvedAssessmentTest().getTestLookup().getBadResourceException();
StringBuilder out = new StringBuilder();
BadRessourceHelper.extractMessage(e, out);
log.info(out.toString());
Assert.assertTrue(test.getModelValidationErrors().isEmpty());
}
}
\ No newline at end of file
......@@ -22,12 +22,13 @@ package org.olat.ims.qti21.model.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.ContentPackageResource;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.ImsManifestException;
......@@ -51,10 +52,10 @@ public class ManifestPackageTest {
Assert.assertNotNull(testFilename);
Assert.assertNotNull(itemFilename);
File tmpDir = Files.createTempDirectory("manifests").toFile();
if(!tmpDir.exists()) {
tmpDir.mkdirs();
}
File tmpDir = new File(WebappHelper.getTmpDir(), "itembuilder" + UUID.randomUUID());
tmpDir.mkdirs();
File manifestFile = new File(tmpDir, "imsmanifest.xml");
FileOutputStream out = new FileOutputStream(manifestFile);
......@@ -71,7 +72,6 @@ public class ManifestPackageTest {
ManifestBuilder reloadManifest = ManifestBuilder.read(manifestFile);
Assert.assertNotNull(reloadManifest);
FileUtils.deleteDirsAndFiles(tmpDir.toPath());
}
}
......@@ -24,10 +24,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collection;
import java.util.UUID;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
......@@ -44,6 +45,7 @@ import org.junit.runners.Parameterized.Parameters;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import org.xml.sax.SAXException;
......@@ -84,14 +86,12 @@ public class OnyxToQtiAssessementItemsTest {
@Test
public void fixItem()
throws IOException, XMLStreamException, SAXException, ParserConfigurationException {
throws IOException, XMLStreamException, SAXException, ParserConfigurationException, URISyntaxException {
URL xmlUrl = OnyxToQtiAssessementItemsTest.class.getResource(xmlFilename);
File xmlFile = new File(xmlUrl.getFile());
File tmpDir = Files.createTempDirectory("onyx").toFile();
if(!tmpDir.exists()) {
tmpDir.mkdirs();
}
File xmlFile = new File(xmlUrl.toURI());
File tmpDir = new File(WebappHelper.getTmpDir(), "onyx" + UUID.randomUUID());
tmpDir.mkdirs();
File outFile = new File(tmpDir, "text.xml");
OutputStream byteOut = new FileOutputStream(outFile);
OutputStreamWriter out = new OutputStreamWriter(byteOut, "UTF8");
......@@ -107,7 +107,6 @@ public class OnyxToQtiAssessementItemsTest {
out.flush();
byteOut.flush();
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(outFile.toPath());
......
......@@ -20,19 +20,39 @@
package org.olat.ims.qti21.pool;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.Locale;
import java.util.UUID;
import org.dom4j.Document;
import org.jcodec.common.Assert;
import org.junit.Test;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.xml.XMLParser;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import org.olat.ims.qti.editor.beecom.objects.QTIDocument;
import org.olat.ims.qti.editor.beecom.parser.ParserManager;
import org.olat.ims.qti21.model.xml.BadRessourceHelper;
import org.olat.ims.resources.IMSEntityResolver;
import uk.ac.ed.ph.jqtiplus.JqtiExtensionManager;
import uk.ac.ed.ph.jqtiplus.notification.Notification;
import uk.ac.ed.ph.jqtiplus.provision.BadResourceException;
import uk.ac.ed.ph.jqtiplus.reading.AssessmentObjectXmlLoader;
import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.ImsManifestException;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.QtiContentPackageExtractor;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.QtiContentPackageSummary;
import uk.ac.ed.ph.jqtiplus.validation.ItemValidationResult;
import uk.ac.ed.ph.jqtiplus.validation.TestValidationResult;
import uk.ac.ed.ph.jqtiplus.xmlutils.XmlResourceNotFoundException;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
/**
*
* Initial date: 19.02.2016<br>
......@@ -44,16 +64,75 @@ public class QTI12To21ConverterTest {
private static final OLog log = Tracing.createLoggerFor(QTI12To21ConverterTest.class);
@Test
public void convert() throws URISyntaxException {
public void convert() throws URISyntaxException, IOException, XmlResourceNotFoundException, ImsManifestException {
QTIDocument doc = loadDocument("qti12_4questiontypes.xml");
File exportDir = new File("/HotCoffee/QTI/today/");
File exportDir = new File(WebappHelper.getTmpDir(), "qti12to21" + UUID.randomUUID());
exportDir.mkdirs();
QTI12To21Converter converter = new QTI12To21Converter(exportDir, Locale.ENGLISH);
converter.convert(doc);
int validAssessmentItems = 0;
boolean validAssessmentTest = false;
QtiContentPackageSummary readableManifest = null;
File[] generatedFiles = exportDir.listFiles();
for(File generatedFile:generatedFiles) {
String filename = generatedFile.getName();
if(filename.equals("imsmanifest.xml")) {
readableManifest = new QtiContentPackageExtractor(exportDir).parse();
} else if(filename.startsWith("test")) {
validAssessmentTest = validateAssessmentTest(generatedFile);
} else if(filename.endsWith(".xml")) {
boolean validItem = validateAssessmentItem(generatedFile);
if(validItem) {
validAssessmentItems++;
}
}
}
//delete tmp
FileUtils.deleteDirsAndFiles(exportDir.toPath());
Assert.assertTrue(validAssessmentTest);
Assert.assertEquals(4, validAssessmentItems);
Assert.assertEquals(1, readableManifest.getTestResources().size());
Assert.assertEquals(4, readableManifest.getItemResources().size());
}
private boolean validateAssessmentTest(File assessmentTestFile) {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(assessmentTestFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
TestValidationResult test = assessmentObjectXmlLoader.loadResolveAndValidateTest(assessmentTestFile.toURI());
for(Notification notification: test.getModelValidationErrors()) {
log.error(notification.getQtiNode() + " : " + notification.getMessage());
}
BadResourceException e = test.getResolvedAssessmentTest().getTestLookup().getBadResourceException();
if(e != null) {
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
}
return test.getModelValidationErrors().isEmpty();
}
private boolean validateAssessmentItem(File assessmentItemFile) {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(assessmentItemFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
ItemValidationResult itemResult = assessmentObjectXmlLoader.loadResolveAndValidateItem(assessmentItemFile.toURI());
BadResourceException e = itemResult.getResolvedAssessmentItem().getItemLookup().getBadResourceException();
if(e != null) {
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
}
return itemResult.getModelValidationErrors().isEmpty();
}
private QTIDocument loadDocument(String filename) {
......
......@@ -21,24 +21,14 @@
<item ident="QTIEDIT:SCQ:8000138058" title="Neue Frage">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Neue Frage<br /><br /><span id="olatFlashMovieViewer549242" class="olatFlashMovieViewer" style="display:block;border:solid 1px #000; width:320px; height:240px;">
<script src="/raw/fx-111111x11/movie/player.js" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
BPlayer.insertPlayer("media/demo-video.mp4","olatFlashMovieViewer549242",320,240,0,0,"video",undefined,false,false,true,undefined);
</script>
</span>]]></mattext>
<mattext texttype="text/html"><![CDATA[Neue Frage]]></mattext>
</material>
<response_lid ident="8000138060" rcardinality="Single" rtiming="No">
<render_choice shuffle="No" minnumber="1" maxnumber="1">
<flow_label class="List">
<response_label ident="8000138063" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Richtige Antwort<br /><br /><span id="olatFlashMovieViewer656727" class="olatFlashMovieViewer" style="display:block;border:solid 1px #000; width:320px; height:240px;">
<script src="/raw/fx-111111x11/movie/player.js" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
BPlayer.insertPlayer("media/demo-video.mp4","olatFlashMovieViewer656727",320,240,0,0,"video",undefined,false,false,true,undefined);
</script>
</span>]]></mattext>
<mattext texttype="text/html"><![CDATA[Richtige Antwort]]></mattext>
</material>
</response_label>
</flow_label>
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE questestinterop SYSTEM "ims_qtiasiv1p2p1.dtd">
<questestinterop>
<assessment ident="test8_8_84528095851561" title="E4 - Test SR">
<qtimetadata>
<qtimetadatafield>
<fieldlabel>qmd_assessmenttype</fieldlabel>
<fieldentry>Assessment</fieldentry>
</qtimetadatafield>
</qtimetadata>
<selection_ordering>
<selection/>
<order order_type="Sequential"/>
</selection_ordering>
<section ident="test8_8_84528095851562" title="Neue Sektion">
<selection_ordering>
<selection/>
<order order_type="Sequential"/>
</selection_ordering>
<item ident="QTIEDIT:SCQ:8000138058" title="Neue Frage">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Neue Frage<br /><br /><span id="olatFlashMovieViewer549242" class="olatFlashMovieViewer" style="display:block;border:solid 1px #000; width:320px; height:240px;">
<script src="/raw/fx-111111x11/movie/player.js" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
BPlayer.insertPlayer("media/demo-video.mp4","olatFlashMovieViewer549242",320,240,0,0,"video",undefined,false,false,true,undefined);
</script>
</span>]]></mattext>
</material>
<response_lid ident="8000138060" rcardinality="Single" rtiming="No">
<render_choice shuffle="No" minnumber="1" maxnumber="1">
<flow_label class="List">
<response_label ident="8000138063" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Richtige Antwort<br /><br /><span id="olatFlashMovieViewer656727" class="olatFlashMovieViewer" style="display:block;border:solid 1px #000; width:320px; height:240px;">
<script src="/raw/fx-111111x11/movie/player.js" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
BPlayer.insertPlayer("media/demo-video.mp4","olatFlashMovieViewer656727",320,240,0,0,"video",undefined,false,false,true,undefined);
</script>
</span>]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000146297" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Falsche Antwort]]></mattext>
</material>
</response_label>
</flow_label>
</render_choice>
</response_lid>
</presentation>
<resprocessing>
<outcomes>
<decvar varname="SCORE" vartype="Decimal" defaultval="0" minvalue="0.0" maxvalue="1.0" cutvalue="1.0"/>
</outcomes>
<respcondition title="Mastery" continue="Yes">
<conditionvar>
<varequal respident="8000138060" case="Yes">8000138063</varequal>
</conditionvar>
<setvar varname="SCORE" action="Set">1.0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Mastery"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<or>
<varequal respident="8000138060" case="Yes">8000146297</varequal>
</or>
</conditionvar>
<setvar varname="SCORE" action="Set">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000138060" case="Yes">8000138063</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000138063"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000138060" case="Yes">8000146297</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000146297"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<other/>
</conditionvar>
<setvar varname="SCORE" action="Set">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
</resprocessing>
</item>
<item ident="QTIEDIT:MCQ:8000150743" title="Multiple Frage">
<itemcontrol feedbackswitch="No" hintswitch="No" solutionswitch="No"/>
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Neue Frage]]></mattext>
</material>
<response_lid ident="8000150745" rcardinality="Multiple" rtiming="No">
<render_choice shuffle="No" minnumber="0" maxnumber="4">
<flow_label class="List">
<response_label ident="8000150748" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Richtige Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000152077" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Falsche Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000152080" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Richtige Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000152091" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[Falsche Antwort]]></mattext>
</material>
</response_label>
</flow_label>
</render_choice>
</response_lid>
</presentation>
<resprocessing>
<outcomes>
<decvar varname="SCORE" vartype="Decimal" defaultval="0" minvalue="0.0" maxvalue="1.0" cutvalue="1.0"/>
</outcomes>
<respcondition title="Mastery" continue="Yes">
<conditionvar>
<and>
<varequal respident="8000150745" case="Yes">8000150748</varequal>
<varequal respident="8000150745" case="Yes">8000152080</varequal>
</and>
<not>
<or>
<varequal respident="8000150745" case="Yes">8000152077</varequal>
<varequal respident="8000150745" case="Yes">8000152091</varequal>
</or>
</not>
</conditionvar>
<setvar varname="SCORE" action="Set">1.0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Mastery"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<or>
<varequal respident="8000150745" case="Yes">8000152077</varequal>
<varequal respident="8000150745" case="Yes">8000152091</varequal>
</or>
</conditionvar>
<setvar varname="SCORE" action="Set">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000150745" case="Yes">8000150748</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000150748"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000150745" case="Yes">8000152077</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000152077"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000150745" case="Yes">8000152080</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000152080"/>
</respcondition>
<respcondition title="_olat_resp_feedback" continue="Yes">
<conditionvar>
<varequal respident="8000150745" case="Yes">8000152091</varequal>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="8000152091"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<other/>
</conditionvar>
<setvar varname="SCORE" action="Set">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
</resprocessing>
<itemfeedback ident="Hint" view="All">
<hint feedbackstyle="Incremental">
<hintmaterial>
<material>
<mattext><![CDATA[
]]></mattext>
</material>
</hintmaterial>
</hint>
</itemfeedback>
<itemfeedback ident="Solution" view="All">
<solution>
<solutionmaterial>
<material>
<mattext><![CDATA[
]]></mattext>
</material>
</solutionmaterial>
</solution>
</itemfeedback>
</item>
<item ident="QTIEDIT:KPRIM:8000171225" title="Neue Frage">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Neue Frage]]></mattext>
</material>
<response_lid ident="8000171227" rcardinality="Multiple" rtiming="No">
<render_choice shuffle="No" minnumber="0" maxnumber="4">
<flow_label class="List">
<response_label ident="8000171230" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[+ Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000171233" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[- Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000171236" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[+ Antwort]]></mattext>
</material>
</response_label>
</flow_label>
<flow_label class="List">
<response_label ident="8000171239" rshuffle="Yes">
<material>
<mattext texttype="text/html"><![CDATA[- Antwort]]></mattext>
</material>
</response_label>
</flow_label>
</render_choice>
</response_lid>
</presentation>
<resprocessing>
<outcomes>
<decvar varname="SCORE" vartype="Decimal" defaultval="0" minvalue="0.0" maxvalue="1.0" cutvalue="1.0"/>
</outcomes>
<respcondition continue="Yes" title="Mastery">
<conditionvar>
<varequal respident="8000171227" case="Yes">8000171230:correct</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Fail">
<conditionvar>
<not>
<varequal respident="8000171227" case="Yes">8000171230:correct</varequal>
</not>
</conditionvar>
<setvar varname="SCORE" action="Add">-0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Mastery">
<conditionvar>
<varequal respident="8000171227" case="Yes">8000171233:wrong</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Fail">
<conditionvar>
<not>
<varequal respident="8000171227" case="Yes">8000171233:wrong</varequal>
</not>
</conditionvar>
<setvar varname="SCORE" action="Add">-0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Mastery">
<conditionvar>
<varequal respident="8000171227" case="Yes">8000171236:correct</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Fail">
<conditionvar>
<not>
<varequal respident="8000171227" case="Yes">8000171236:correct</varequal>
</not>
</conditionvar>
<setvar varname="SCORE" action="Add">-0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Mastery">
<conditionvar>
<varequal respident="8000171227" case="Yes">8000171239:wrong</varequal>
</conditionvar>
<setvar varname="SCORE" action="Add">0.25</setvar>
</respcondition>
<respcondition continue="Yes" title="Fail">
<conditionvar>
<not>
<varequal respident="8000171227" case="Yes">8000171239:wrong</varequal>
</not>
</conditionvar>
<setvar varname="SCORE" action="Add">-0.25</setvar>
</respcondition>
<respcondition title="Mastery" continue="Yes">
<conditionvar>
<and>
<varequal respident="8000171227" case="Yes">8000171230:correct</varequal>
<varequal respident="8000171227" case="Yes">8000171233:wrong</varequal>
<varequal respident="8000171227" case="Yes">8000171236:correct</varequal>
<varequal respident="8000171227" case="Yes">8000171239:wrong</varequal>
</and>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="Mastery"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<not>
<and>
<varequal respident="8000171227" case="Yes">8000171230:correct</varequal>
<varequal respident="8000171227" case="Yes">8000171233:wrong</varequal>
<varequal respident="8000171227" case="Yes">8000171236:correct</varequal>
<varequal respident="8000171227" case="Yes">8000171239:wrong</varequal>
</and>
</not>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
</resprocessing>
</item>
<item ident="QTIEDIT:FIB:8000173476" title="Lückentext Frage">
<itemcontrol feedbackswitch="No" hintswitch="No" solutionswitch="No"/>
<presentation label="notset">
<flow>
<material>
<mattext texttype="text/html"><![CDATA[To be or]]></mattext>
</material>
<response_str ident="8000177110" rcardinality="Single">
<render_fib columns="3" maxchars="10">
<flow_label class="Block">
<response_label ident="8000177110" rshuffle="Yes"/>
</flow_label>
</render_fib>
</response_str>
<material>
<mattext texttype="text/html"><![CDATA[<p>to be</p>]]></mattext>
</material>
</flow>
</presentation>
<resprocessing>
<outcomes>
<decvar varname="SCORE" vartype="Decimal" defaultval="0" minvalue="0.0" maxvalue="1.0" cutvalue="1.0"/>
</outcomes>
<respcondition title="Mastery" continue="Yes">
<conditionvar>
<and>
<or>
<varequal respident="8000177110" case="No"><![CDATA[New text element<br />Et encor<br />bla]]></varequal>
</or>
</and>
</conditionvar>
<setvar varname="SCORE" action="Set">1.0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Mastery"/>
</respcondition>
<respcondition title="Fail" continue="Yes">
<conditionvar>
<other/>
</conditionvar>
<setvar varname="SCORE" action="Set">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="Fail"/>
<displayfeedback feedbacktype="Solution" linkrefid="Solution"/>
<displayfeedback feedbacktype="Hint" linkrefid="Hint"/>
</respcondition>
</resprocessing>
<itemfeedback ident="Hint" view="All">
<hint feedbackstyle="Incremental">
<hintmaterial>
<material>
<mattext><![CDATA[
]]></mattext>
</material>
</hintmaterial>
</hint>
</itemfeedback>
<itemfeedback ident="Solution" view="All">
<solution>
<solutionmaterial>
<material>
<mattext><![CDATA[
]]></mattext>
</material>
</solutionmaterial>
</solution>
</itemfeedback>
</item>
</section>
</assessment>
</questestinterop>
......@@ -20,8 +20,34 @@
package org.olat.ims.qti21.repository.handlers;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.WebappHelper;
import org.olat.fileresource.types.ImsQTI21Resource.PathResourceLocator;
import org.olat.ims.qti21.model.xml.BadRessourceHelper;
import org.olat.test.OlatTestCase;
import org.springframework.beans.factory.annotation.Autowired;
import uk.ac.ed.ph.jqtiplus.JqtiExtensionManager;
import uk.ac.ed.ph.jqtiplus.notification.Notification;
import uk.ac.ed.ph.jqtiplus.provision.BadResourceException;
import uk.ac.ed.ph.jqtiplus.reading.AssessmentObjectXmlLoader;
import uk.ac.ed.ph.jqtiplus.reading.QtiXmlReader;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.ContentPackageResource;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.ImsManifestException;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.QtiContentPackageExtractor;
import uk.ac.ed.ph.jqtiplus.utils.contentpackaging.QtiContentPackageSummary;
import uk.ac.ed.ph.jqtiplus.validation.ItemValidationResult;
import uk.ac.ed.ph.jqtiplus.validation.TestValidationResult;
import uk.ac.ed.ph.jqtiplus.xmlutils.XmlResourceNotFoundException;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
/**
*
......@@ -29,18 +55,104 @@ import org.junit.Test;
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class QTI21AssessmentTestHandlerTest {
public class QTI21AssessmentTestHandlerTest extends OlatTestCase {
private static final File fullPackage = new File("/Users/srosse/Desktop/QTI/Full/");
private static final OLog log = Tracing.createLoggerFor(QTI21AssessmentTestHandlerTest.class);
@Autowired
private QTI21AssessmentTestHandler testHandler;
/**
* The test creates a QTI 2.1 test with the QTI handler and check if all
* the elements are valid, assessment test, assessment item and
* manifest.
*
* @throws IOException
* @throws XmlResourceNotFoundException
* @throws ImsManifestException
*/
@Test
public void createImsManifest() {
if(!fullPackage.exists()) {
fullPackage.mkdirs();
public void createAssessmentTest() throws IOException, XmlResourceNotFoundException, ImsManifestException {
File tmpDir = new File(WebappHelper.getTmpDir(), "qti21fullpackage" + UUID.randomUUID());
tmpDir.mkdirs();
testHandler.createMinimalAssessmentTest("Generated test", tmpDir);
boolean foundImsManifest = false;
boolean foundAssessmentTest = false;
boolean foundAssessmentItem = false;
boolean validAssessmentTest = false;
boolean validAssessmentItem = false;
boolean readableManifest = false;
File[] generatedFiles = tmpDir.listFiles();
for(File generatedFile:generatedFiles) {
String filename = generatedFile.getName();
if(filename.equals("imsmanifest.xml")) {
foundImsManifest = true;
readableManifest = readManifest(tmpDir);
} else if(filename.startsWith("test")) {
foundAssessmentTest = true;
validAssessmentTest = validateAssessmentTest(generatedFile);
} else if(filename.startsWith("sc")) {
foundAssessmentItem = true;
validAssessmentItem = validateAssessmentItem(generatedFile);
}
}
QTI21AssessmentTestHandler handler = new QTI21AssessmentTestHandler();
handler.createMinimalAssessmentTest("Generated test", fullPackage);
//delete tmp
FileUtils.deleteDirsAndFiles(tmpDir.toPath());
//checks
Assert.assertTrue(foundImsManifest);
Assert.assertTrue(foundAssessmentTest);
Assert.assertTrue(foundAssessmentItem);
Assert.assertTrue(validAssessmentTest);
Assert.assertTrue(validAssessmentItem);
Assert.assertTrue(readableManifest);
}
private boolean validateAssessmentTest(File assessmentTestFile) {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(assessmentTestFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
TestValidationResult test = assessmentObjectXmlLoader.loadResolveAndValidateTest(assessmentTestFile.toURI());
for(Notification notification: test.getModelValidationErrors()) {
log.error(notification.getQtiNode() + " : " + notification.getMessage());
}
BadResourceException e = test.getResolvedAssessmentTest().getTestLookup().getBadResourceException();
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
return test.getModelValidationErrors().isEmpty();
}
private boolean validateAssessmentItem(File assessmentItemFile) {
QtiXmlReader qtiXmlReader = new QtiXmlReader(new JqtiExtensionManager());
ResourceLocator fileResourceLocator = new PathResourceLocator(assessmentItemFile.toPath());
AssessmentObjectXmlLoader assessmentObjectXmlLoader = new AssessmentObjectXmlLoader(qtiXmlReader, fileResourceLocator);
ItemValidationResult itemResult = assessmentObjectXmlLoader.loadResolveAndValidateItem(assessmentItemFile.toURI());
BadResourceException e = itemResult.getResolvedAssessmentItem().getItemLookup().getBadResourceException();
if(e != null) {
StringBuilder err = new StringBuilder();
BadRessourceHelper.extractMessage(e, err);
log.error(err.toString());
}
return itemResult.getModelValidationErrors().isEmpty();
}
private boolean readManifest(File tmpDir) throws ImsManifestException, XmlResourceNotFoundException {
QtiContentPackageExtractor extractor = new QtiContentPackageExtractor(tmpDir);
QtiContentPackageSummary summary = extractor.parse();
List<ContentPackageResource> items = summary.getItemResources();
List<ContentPackageResource> tests = summary.getTestResources();
return items.size() == 1 && tests.size() == 1;
}
}
......@@ -193,7 +193,8 @@ import org.junit.runners.Suite;
org.olat.ims.qti21.model.xml.AssessmentHtmlBuilderTest.class,
org.olat.ims.qti21.model.xml.AssessmentItemPackageTest.class,
org.olat.ims.qti21.model.xml.ManifestPackageTest.class,
//org.olat.ims.qti21.model.xml.OnyxToQtiAssessementItemsTest.class,
org.olat.ims.qti21.repository.handlers.QTI21AssessmentTestHandlerTest.class,
org.olat.ims.qti21.model.xml.OnyxToQtiAssessementItemsTest.class,
org.olat.ims.lti.LTIManagerTest.class,
org.olat.modules.webFeed.FeedManagerImplTest.class,
org.olat.modules.qpool.manager.MetadataConverterHelperTest.class,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment