diff --git a/pom.xml b/pom.xml
index 187f8a37c3f1c339e14d387ffd8a1d44b2714ef0..1e1fc74575defc9bbd1675e1ccda12ce2be31c4d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1997,7 +1997,7 @@
 		<dependency>
 			<groupId>org.openolat.imscp</groupId>
 			<artifactId>manifest</artifactId>
-			<version>1.3-SNAPSHOT</version>
+			<version>1.3.0</version>
 		</dependency>
 		<dependency>
 			<groupId>rome</groupId>
diff --git a/src/main/java/org/olat/ims/qti21/AssessmentTestSession.java b/src/main/java/org/olat/ims/qti21/AssessmentTestSession.java
index 5cd84eb67c3fc2a82be399d67f9ba897ced023de..c88f11fb2d980789422802c072d3bf2bb6c96a5a 100644
--- a/src/main/java/org/olat/ims/qti21/AssessmentTestSession.java
+++ b/src/main/java/org/olat/ims/qti21/AssessmentTestSession.java
@@ -72,6 +72,8 @@ public interface AssessmentTestSession extends CreateInfo, ModifiedInfo {
 	
 	public boolean isExploded();
 	
+	public void setExploded(boolean exploded);
+	
 	public String getStorage();
 	
 	
diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java
index d2617ff29734ef2a08298dc2931d4eec0b973742..f3366585906b19e840688e06a007818c87d1e9b8 100644
--- a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java
@@ -19,6 +19,8 @@
  */
 package org.olat.ims.qti21.ui;
 
+import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.testFeedbackVisible;
+
 import java.io.File;
 import java.math.BigDecimal;
 import java.net.URI;
@@ -109,6 +111,8 @@ import uk.ac.ed.ph.jqtiplus.node.result.TestResult;
 import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
 import uk.ac.ed.ph.jqtiplus.node.test.NavigationMode;
 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.TestFeedbackAccess;
 import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
 import uk.ac.ed.ph.jqtiplus.notification.NotificationLevel;
 import uk.ac.ed.ph.jqtiplus.notification.NotificationRecorder;
@@ -658,7 +662,7 @@ public class AssessmentTestDisplayController extends BasicController implements
             TestPlanNodeKey itemNodeKey = testSessionState.getCurrentItemKey();
             if(itemNodeKey != null) {
 				TestPlanNode currentItemNode = testSessionState.getTestPlan().getNode(itemNodeKey);
-	        	boolean hasFeedbacks = qtiWorksCtrl.willShowSomeFeedbacks(currentItemNode);
+	        	boolean hasFeedbacks = qtiWorksCtrl.willShowSomeAssessmentItemFeedbacks(currentItemNode);
 	        	//allow skipping
 	        	if(!hasFeedbacks) {
 	        		processNextItem(ureq);
@@ -999,6 +1003,40 @@ public class AssessmentTestDisplayController extends BasicController implements
         if(nextTestPart == null) {
         	candidateSession = qtiService.finishTestSession(candidateSession, testSessionState, assessmentResult,
         			requestTimestamp, getDigitalSignatureOptions(), getIdentity());
+        	if(!qtiWorksCtrl.willShowSomeAssessmentTestFeedbacks()) {
+        		//need feedback, no more parts, quickly exit
+        		try {
+        			//end current test part
+                    testSessionController.enterNextAvailableTestPart(requestTimestamp);
+                } catch (final QtiCandidateStateException e) {
+                    candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_ADVANCE_TEST_PART, e);
+                    logError("CANNOT_ADVANCE_TEST_PART", e);
+                    return;
+                } catch (final RuntimeException e) {
+                    candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.CANNOT_ADVANCE_TEST_PART, e);
+                    logError("RuntimeException", e);
+                    return;// handleExplosion(e, candidateSession);
+                }
+
+        		//exit the test
+                NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
+                CandidateTestEventType eventType = CandidateTestEventType.EXIT_TEST;
+                testSessionController.exitTest(requestTimestamp);
+                candidateSession.setTerminationTime(requestTimestamp);
+                candidateSession = qtiService.updateAssessmentTestSession(candidateSession);
+        		
+        		/* Record and log event */
+                final CandidateEvent candidateTestEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry,
+                       eventType, testSessionState, notificationRecorder);
+                candidateAuditLogger.logCandidateEvent(candidateTestEvent);
+                this.lastEvent = candidateTestEvent;
+
+                qtiWorksCtrl.updateStatusAndResults(ureq);
+        		doExitTest(ureq);
+        	}
+        } else if(!qtiWorksCtrl.willShowSomeTestPartFeedbacks()) {
+        	//no feedback, go to the next part
+        	processAdvanceTestPart(ureq);
         }
 	}
 	
@@ -1366,10 +1404,14 @@ public class AssessmentTestDisplayController extends BasicController implements
 
 		BadResourceException ex = resolvedAssessmentTest.getTestLookup().getBadResourceException();
 		if(ex instanceof QtiXmlInterpretationException) {
-			QtiXmlInterpretationException exml = (QtiXmlInterpretationException)ex;
-			System.out.println(exml.getInterpretationFailureReason());
-			for(QtiModelBuildingError err :exml.getQtiModelBuildingErrors()) {
-				System.out.println(err);
+			try {//try to log some informations
+				QtiXmlInterpretationException exml = (QtiXmlInterpretationException)ex;
+				logError(exml.getInterpretationFailureReason().toString(), null);
+				for(QtiModelBuildingError err :exml.getQtiModelBuildingErrors()) {
+					logError(err.toString(), null);
+				}
+			} catch (Exception e) {
+				logError("", e);
 			}
 		}
 		
@@ -1525,7 +1567,7 @@ public class AssessmentTestDisplayController extends BasicController implements
 			updateStatusAndResults(ureq);
 		}
 		
-		public boolean willShowSomeFeedbacks(TestPlanNode itemNode) {
+		public boolean willShowSomeAssessmentItemFeedbacks(TestPlanNode itemNode) {
 			if(itemNode == null || testSessionController == null
 					|| testSessionController.getTestSessionState().isExited()
 					|| testSessionController.getTestSessionState().isEnded()) {
@@ -1534,6 +1576,77 @@ public class AssessmentTestDisplayController extends BasicController implements
 			
 			return qtiEl.getComponent().willShowFeedbacks(itemNode);
 		}
+		
+		/**
+		 * 
+		 * @return
+		 */
+		public boolean willShowSomeAssessmentTestFeedbacks() {
+			if(testSessionController == null
+					|| testSessionController.getTestSessionState().isExited()
+					|| testSessionController.getTestSessionState().isEnded()) {
+				return true;
+			}
+			
+			TestSessionState testSessionState = testSessionController.getTestSessionState();
+			TestPlanNodeKey currentTestPartNodeKey = testSessionState.getCurrentTestPartKey();
+			TestPlanNode currentTestPlanNode = testSessionState.getTestPlan().getNode(currentTestPartNodeKey);
+			boolean hasReviewableItems = currentTestPlanNode.searchDescendants(TestNodeType.ASSESSMENT_ITEM_REF)
+					.stream().anyMatch(itemNode
+							-> itemNode.getEffectiveItemSessionControl().isAllowReview()
+							|| itemNode.getEffectiveItemSessionControl().isShowFeedback());
+			if(hasReviewableItems) {
+				return true;
+			}
+			
+			//Show 'atEnd' test feedback f there's only 1 testPart
+			List<TestFeedback> testFeedbacks = qtiEl.getComponent().getAssessmentTest().getTestFeedbacks();
+			for(TestFeedback testFeedback:testFeedbacks) {
+				if(testFeedback.getTestFeedbackAccess() == TestFeedbackAccess.AT_END
+						&& testFeedbackVisible(testFeedback, testSessionController.getTestSessionState())) {
+					return true;
+				}
+			}
+			
+			return false;
+		}
+		
+		/**
+		 * 
+		 * Check if the current test part will show some test part feedback,
+		 * item feedback or item reviews.
+		 * 
+		 * @return
+		 */
+		public boolean willShowSomeTestPartFeedbacks() {
+			if(testSessionController == null
+					|| testSessionController.getTestSessionState().isExited()
+					|| testSessionController.getTestSessionState().isEnded()) {
+				return true;
+			}
+			
+			TestSessionState testSessionState = testSessionController.getTestSessionState();
+			TestPlanNodeKey currentTestPartNodeKey = testSessionState.getCurrentTestPartKey();
+			TestPlanNode currentTestPlanNode = testSessionState.getTestPlan().getNode(currentTestPartNodeKey);
+			boolean hasReviewableItems = currentTestPlanNode.searchDescendants(TestNodeType.ASSESSMENT_ITEM_REF)
+					.stream().anyMatch(itemNode
+							-> itemNode.getEffectiveItemSessionControl().isAllowReview()
+							|| itemNode.getEffectiveItemSessionControl().isShowFeedback());
+			if(hasReviewableItems) {
+				return true;
+			}
+
+			TestPart currentTestPart = testSessionController.getCurrentTestPart();
+			List<TestFeedback> testFeedbacks = currentTestPart.getTestFeedbacks();
+			for(TestFeedback testFeedback:testFeedbacks) {
+				if(testFeedback.getTestFeedbackAccess() == TestFeedbackAccess.AT_END
+						&& testFeedbackVisible(testFeedback, testSessionController.getTestSessionState())) {
+					return true;
+				}
+			}
+			
+			return false;
+		}
 
 		@Override
 		protected Identifier getResponseIdentifierFromUniqueId(String uniqueId) {
diff --git a/src/main/java/org/olat/ims/qti21/ui/_content/suspended.html b/src/main/java/org/olat/ims/qti21/ui/_content/suspended.html
index c0282a636250948871a78ab6a19528c40ab6e539..bcd24f92b6678d0a1f07988d9e8339ebac8c2c0d 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_content/suspended.html
+++ b/src/main/java/org/olat/ims/qti21/ui/_content/suspended.html
@@ -1,3 +1,16 @@
 <div id="o_qti_container">
 	<div class="o_important">$r.translate("assessment.test.suspended")</div>
-</div>
\ No newline at end of file
+</div>
+<script type="text/javascript">
+/* <![CDATA[ */
+jQuery(function() {
+	try {
+		if(!(typeof window.qti21TestTimer === "undefined")) {
+			window.qti21TestTimer.cancel();
+		}
+	} catch(e) {
+		if(window.console) console.log(e);
+	}
+});
+/* ]]> */
+</script>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
index c2124c674dd8e16e5a562076fe9951d1d340ba04..dba3dc47be29c8a08c8300893249adf3058c845a 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java
@@ -197,7 +197,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent
     }
 
     protected void renderTerminated(StringOutput sb, Translator translator) {
-		sb.append("<div class='o_info'>").append(translator.translate("terminated.msg")).append("</div>");
+		sb.append("<div class='o_info o_sel_assessment_test_terminated'>").append(translator.translate("terminated.msg")).append("</div>");
     }
 	
 	protected void renderItemStatus(StringOutput sb, ItemSessionState itemSessionState, RenderingRequest options, Translator translator) {
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
index d6928f5fde1d5d012d9b6fff453be90110b12bd9..fa42cc925c4f0c2520c3264ac6e84012787b0460 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java
@@ -49,9 +49,11 @@ import uk.ac.ed.ph.jqtiplus.node.item.CorrectResponse;
 import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.Choice;
 import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
 import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration;
+import uk.ac.ed.ph.jqtiplus.node.test.TestFeedback;
 import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode;
 import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
 import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
+import uk.ac.ed.ph.jqtiplus.state.TestSessionState;
 import uk.ac.ed.ph.jqtiplus.types.Identifier;
 import uk.ac.ed.ph.jqtiplus.types.ResponseData;
 import uk.ac.ed.ph.jqtiplus.types.StringResponseData;
@@ -623,4 +625,18 @@ public class AssessmentRenderFunctions {
 		String relativePath = component.relativePathTo(resolvedAssessmentItem);
 		return component.getMapperUri() + "/file?href=" + relativePath + (uri == null ? "" : uri);
 	}
+	
+	public static final boolean testFeedbackVisible(TestFeedback testFeedback, TestSessionState testSessionState) {
+		//<xsl:variable name="identifierMatch" select="boolean(qw:value-contains(qw:get-test-outcome-value(@outcomeIdentifier), @identifier))" as="xs:boolean"/>
+		Identifier outcomeIdentifier = testFeedback.getOutcomeIdentifier();
+		Value outcomeValue = testSessionState.getOutcomeValue(outcomeIdentifier);
+		boolean identifierMatch = valueContains(outcomeValue, testFeedback.getOutcomeValue());
+		//<xsl:if test="($identifierMatch and @showHide='show') or (not($identifierMatch) and @showHide='hide')">
+		if((identifierMatch && testFeedback.getVisibilityMode() == VisibilityMode.SHOW_IF_MATCH)
+				|| (!identifierMatch && testFeedback.getVisibilityMode() == VisibilityMode.HIDE_IF_MATCH)) {
+			return true;
+		}
+		return false;
+	}
+	
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponent.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponent.java
index 3e6fc43326aefa20c051476f8b70381954f226d7..cc0f9371546c44353fcf3faab81d3f16370d14d2 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponent.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponent.java
@@ -163,9 +163,7 @@ public class AssessmentTestComponent extends AssessmentObjectComponent  {
 			if(!itemSessionState.isResponded()) {
 				return true;
 			}
-			if(!itemNode.getEffectiveItemSessionControl().isAllowSkipping()) {
-				return true;
-			}
+
 
 			List<Interaction> interactions = assessmentItem.getItemBody().findInteractions();
 			for(Interaction interaction:interactions) {
@@ -178,7 +176,6 @@ public class AssessmentTestComponent extends AssessmentObjectComponent  {
 			}
 
 			ItemProcessingContext itemContext = getTestSessionController().getItemProcessingContext(itemNode);
-			
 			if(assessmentItem.getItemBody().willShowFeedback(itemContext)) {
 				return true;
 			}
diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponentRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponentRenderer.java
index a4e3d8565de2d4d640ff86accec6e6ea4ac7e534..7b582e7278b4fb68ecd23b1ec903ebffbe32360a 100644
--- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponentRenderer.java
+++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentTestComponentRenderer.java
@@ -20,7 +20,7 @@
 package org.olat.ims.qti21.ui.components;
 
 import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.contentAsString;
-import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.valueContains;
+import static org.olat.ims.qti21.ui.components.AssessmentRenderFunctions.testFeedbackVisible;
 
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -72,7 +72,6 @@ import uk.ac.ed.ph.jqtiplus.node.test.NavigationMode;
 import uk.ac.ed.ph.jqtiplus.node.test.TestFeedback;
 import uk.ac.ed.ph.jqtiplus.node.test.TestFeedbackAccess;
 import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
-import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode;
 import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
 import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
 import uk.ac.ed.ph.jqtiplus.state.AssessmentSectionSessionState;
@@ -455,9 +454,9 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
 		renderTestFeebacks(renderer, sb, currentTestPart.getTestFeedbacks(), component, TestFeedbackAccess.AT_END, ubu, translator);
 
 		//Show 'atEnd' test feedback f there's only 1 testPart
-		if(!component.hasMultipleTestParts()) {
-			renderTestFeebacks(renderer, sb, component.getAssessmentTest().getTestFeedbacks(), component, TestFeedbackAccess.AT_END, ubu, translator);
-		}
+		//if(!component.hasMultipleTestParts()) {
+		renderTestFeebacks(renderer, sb, component.getAssessmentTest().getTestFeedbacks(), component, TestFeedbackAccess.AT_END, ubu, translator);
+		//}
 		
 		//test part review
 		component.getTestSessionController().getTestSessionState().getTestPlan()
@@ -579,24 +578,20 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
 	
 	private void renderTestFeeback(AssessmentRenderer renderer, StringOutput sb, AssessmentTestComponent component, TestFeedback testFeedback,
 			URLBuilder ubu, Translator translator) {
-		//<xsl:variable name="identifierMatch" select="boolean(qw:value-contains(qw:get-test-outcome-value(@outcomeIdentifier), @identifier))" as="xs:boolean"/>
-		Identifier outcomeIdentifier = testFeedback.getOutcomeIdentifier();
-		Value outcomeValue = component.getTestSessionController().getTestSessionState().getOutcomeValue(outcomeIdentifier);
-		boolean identifierMatch = valueContains(outcomeValue, testFeedback.getOutcomeValue());
-		//<xsl:if test="($identifierMatch and @showHide='show') or (not($identifierMatch) and @showHide='hide')">
-		if((identifierMatch && testFeedback.getVisibilityMode() == VisibilityMode.SHOW_IF_MATCH)
-				|| (!identifierMatch && testFeedback.getVisibilityMode() == VisibilityMode.HIDE_IF_MATCH)) {
-			
-			sb.append("<h2>");
+		TestSessionState testSessionState = component.getTestSessionController().getTestSessionState();
+		if(testFeedbackVisible(testFeedback, testSessionState)) {
+			sb.append("<div class='o_info clearfix'>");
+			sb.append("<h3>");
 			if(StringHelper.containsNonWhitespace(testFeedback.getTitle())) {
 				sb.append(StringHelper.escapeHtml(testFeedback.getTitle()));
 			} else {
 				sb.append(translator.translate("assessment.test.modal.feedback"));
 			}
-			sb.append("</h2>");
+			sb.append("</h3>");
 
 			testFeedback.getChildren().forEach((flow)
 				-> renderFlow(renderer, sb, component, null, null, flow, ubu, translator));
+			sb.append("</div>");
 		}
 	}
 	
diff --git a/src/test/java/org/olat/selenium/AssessmentTest.java b/src/test/java/org/olat/selenium/AssessmentTest.java
index 796cb70f692bca49906cbabd94d72fae1c2babf9..c081ddb80926ecccdc6667815963a2a0f1dfaf01 100644
--- a/src/test/java/org/olat/selenium/AssessmentTest.java
+++ b/src/test/java/org/olat/selenium/AssessmentTest.java
@@ -36,7 +36,6 @@ import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.arquillian.test.api.ArquillianResource;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.Assert;
-import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.olat.selenium.page.LoginPage;
@@ -69,7 +68,6 @@ import org.olat.user.restapi.UserVO;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.firefox.FirefoxDriver;
 
 /**
  * 
@@ -105,9 +103,6 @@ public class AssessmentTest {
 	public void qti12Test(@InitialPage LoginPage authorLoginPage)
 	throws IOException, URISyntaxException {
 		
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-				
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
 		
@@ -200,9 +195,7 @@ public class AssessmentTest {
 	public void qti12CourseWithAssessment(@InitialPage LoginPage authorLoginPage,
 			@Drone @User WebDriver ryomouBrowser)
 	throws IOException, URISyntaxException {
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-		
+
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
 		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
@@ -342,9 +335,7 @@ public class AssessmentTest {
 	public void scormCourseWithAssessment(@InitialPage LoginPage authorLoginPage,
 			@Drone @User WebDriver ryomouBrowser)
 	throws IOException, URISyntaxException {
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-				
+		
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
 		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
@@ -462,9 +453,7 @@ public class AssessmentTest {
 	public void assessmentMode_manual(@InitialPage LoginPage authorLoginPage,
 			@Drone @Student WebDriver ryomouBrowser, @Drone @Participant WebDriver kanuBrowser)
 	throws IOException, URISyntaxException {
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-		
+
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
 		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
@@ -878,9 +867,7 @@ public class AssessmentTest {
 			@Drone @User WebDriver ryomouBrowser,
 			@Drone @Participant WebDriver kanuBrowser)
 	throws IOException, URISyntaxException {
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-						
+			
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		UserVO kanu = new UserRestClient(deploymentUrl).createRandomUser("Kanu");
 		UserVO ryomou = new UserRestClient(deploymentUrl).createRandomUser("Ryomou");
@@ -1066,8 +1053,6 @@ public class AssessmentTest {
 	public void taskWithIndividuScoreAndRevision(@InitialPage LoginPage authorLoginPage,
 			@Drone @User WebDriver ryomouBrowser)
 	throws IOException, URISyntaxException {
-		//File upload only work with Firefox
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
 						
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
 		UserVO kanu = new UserRestClient(deploymentUrl).createRandomUser("kanu");
diff --git a/src/test/java/org/olat/selenium/ImsQTI21Test.java b/src/test/java/org/olat/selenium/ImsQTI21Test.java
index c1e33877c9a1de419e998ef1a198027d87781a55..8e0f6d13d5ac54b1eb1b9e1dbc3270340cb0aace 100644
--- a/src/test/java/org/olat/selenium/ImsQTI21Test.java
+++ b/src/test/java/org/olat/selenium/ImsQTI21Test.java
@@ -73,6 +73,340 @@ public class ImsQTI21Test {
 	@Page
 	private NavigationPage navBar;
 	
+	/**
+	 * Test the flow of the simplest possible test with our
+	 * optimization (jump automatically to the next question,
+	 * jump automatically the close test). The test has one
+	 * part and 2 questions, no feedbacks, no review allowed...
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_noParts_noFeedbacks(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "With parts QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_without_feedbacks.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.assertOnAssessmentItem()
+			.answerSingleChoice("Incorrect response")
+			.saveAnswer()
+			.assertOnAssessmentItem("Second question")
+			.selectItem("First question")
+			.assertOnAssessmentItem("First question")
+			.answerSingleChoice("Correct response")
+			.saveAnswer()
+			.answerMultipleChoice("Correct response")
+			.saveAnswer()
+			.endTest()//auto close because 1 part, no feedbacks
+			.assertOnAssessmentTestTerminated();
+	}
+	
+	/**
+	 * Test the flow of a test with questions feedbacks and test
+	 * feedback.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_noParts_withFeedbacks(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "With parts QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_with_feedbacks.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.assertOnAssessmentItem()
+			.answerSingleChoice("Wrong answer")
+			.saveAnswer()
+			.assertFeedback("Oooops")
+			.answerSingleChoice("Correct answer")
+			.saveAnswer()
+			.assertFeedback("Well done")
+			.nextAnswer()
+			.assertOnAssessmentItem("Numerical entry")
+			.answerGapText("69", "_RESPONSE_1")
+			.saveAnswer()
+			.assertFeedback("Not really")
+			.answerGapText("42", "_RESPONSE_1")
+			.saveAnswer()
+			.assertFeedback("Ok")
+			.endTest()
+			.assertOnAssessmentTestFeedback("All right")
+			.closeTest()
+			.assertOnAssessmentTestTerminated();
+	}
+	
+	/**
+	 * A test with a single part, feedback for questions and
+	 * tests and the resource options "show results at the end
+	 * of the test".
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_noParts_feedbacksAndResults(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "With parts QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_with_feedbacks.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile);
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.clickToolbarBack()
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem()
+			.answerSingleChoice("Wrong answer")
+			.saveAnswer()
+			.assertFeedback("Oooops")
+			.nextAnswer()
+			.assertOnAssessmentItem("Numerical entry")
+			.answerGapText("42", "_RESPONSE_1")
+			.saveAnswer()
+			.assertFeedback("Ok")
+			.endTest()
+			.assertOnAssessmentTestFeedback("Not for the best")
+			.closeTest()
+			.assertOnAssessmentTestMaxScore(2)
+			.assertOnAssessmentTestScore(1)
+			.assertOnAssessmentTestNotPassed();
+	}
+	
+	/**
+	 * A test with a single part, feedback for questions and
+	 * tests and the resource options "show results at the end
+	 * of the test".
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_parts_noFeedbacksButResults(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "With parts QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_parts_without_feedbacks.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile);
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.clickToolbarBack()
+			.options()
+			.showResults(Boolean.TRUE, QTI21AssessmentResultsOptions.allOptions())
+			.save();
+		
+		qtiPage
+			.clickToolbarBack()
+			.startTestPart()
+			.selectItem("First question")
+			.assertOnAssessmentItem("First question")
+			.answerSingleChoice("Correct")
+			.saveAnswer()
+			.assertOnAssessmentItem("Second question")
+			.answerMultipleChoice("True")
+			.saveAnswer()
+			.endTestPart()
+			.selectItem("Third question")
+			.assertOnAssessmentItem("Third question")
+			.answerMultipleChoice("Correct")
+			.saveAnswer()
+			.answerCorrectKPrim("True", "Right")
+			.answerIncorrectKPrim("Wrong", "False")
+			.saveAnswer()
+			.endTestPart()
+			.assertOnAssessmentTestMaxScore(4)
+			.assertOnAssessmentTestScore(4)
+			.assertOnAssessmentTestPassed();
+	}
+	
+	/**
+	 * Test with 2 parts and test feedbacks.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_parts_feedbacks(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "With parts QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_with_parts_and_test_feedbacks.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+
+		qtiPage
+			.startTestPart()
+			.selectItem("First question")
+			.assertOnAssessmentItem("First question")
+			.answerSingleChoice("Correct answer")
+			.saveAnswer()
+			.assertOnAssessmentItem("Second question")
+			.answerMultipleChoice("Valid answer")
+			.saveAnswer()
+			.endTestPart()
+			.selectItem("Third question")
+			.assertOnAssessmentItem("Third question")
+			.answerSingleChoice("Right")
+			.saveAnswer()
+			.answerSingleChoice("Good")
+			.saveAnswer()
+			.endTestPart()
+			.assertOnAssessmentTestFeedback("Well done")
+			.closeTest()
+			.assertOnAssessmentTestTerminated();
+	}
+	
+	/**
+	 * Test with time limit.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_timeLimits(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Timed QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_time_limits.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		//check simple time limit
+		qtiPage
+			.assertOnAssessmentItem("Single choice")
+			.answerSingleChoice("Correct answer")
+			.saveAnswer()
+			.assertOnAssessmentItem("Last choice")
+			.answerSingleChoice("True")
+			.saveAnswer()
+			.assertOnAssessmentTestTerminated(15);
+	}
+	
+	/**
+	 * Test with time limit and wait for the results at the end.
+	 * 
+	 * @param authorLoginPage
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	@RunAsClient
+	public void qti21TestFlow_timeLimits_results(@InitialPage LoginPage authorLoginPage)
+	throws IOException, URISyntaxException {
+		
+		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
+		authorLoginPage.loginAs(author.getLogin(), author.getPassword());
+		
+		//upload a test
+		String qtiTestTitle = "Timed QTI 2.1 " + UUID.randomUUID();
+		URL qtiTestUrl = JunitTestHelper.class.getResource("file_resources/qti21/test_time_limits.zip");
+		File qtiTestFile = new File(qtiTestUrl.toURI());
+		navBar
+			.openAuthoringEnvironment()
+			.uploadResource(qtiTestTitle, qtiTestFile)
+			.clickToolbarRootCrumb();
+		
+		QTI21Page qtiPage = QTI21Page
+				.getQTI12Page(browser);
+		qtiPage
+			.options()
+			.showResults(Boolean.TRUE, new QTI21AssessmentResultsOptions(true, true, false, false, false, false))
+			.save();
+		
+		//check simple time limit
+		qtiPage
+			.clickToolbarBack()
+			.assertOnAssessmentItem("Single choice")
+			.answerSingleChoice("Correct answer")
+			.saveAnswer()
+			.assertOnAssessmentItem("Last choice")
+			.answerSingleChoice("True")
+			.saveAnswer()
+			.assertOnAssessmentResults(15)
+			.assertOnAssessmentTestPassed()
+			.assertOnAssessmentTestMaxScore(2)
+			.assertOnAssessmentTestScore(2);
+	}
+	
 	/**
 	 * Upload a test in QTI 2.1 format, create a course, bind
 	 * the test in a course element, run it and check if
@@ -84,7 +418,7 @@ public class ImsQTI21Test {
 	 */
 	@Test
 	@RunAsClient
-	public void qti21Test(@InitialPage LoginPage authorLoginPage)
+	public void qti21TestInCourse(@InitialPage LoginPage authorLoginPage)
 	throws IOException, URISyntaxException {
 		
 		UserVO author = new UserRestClient(deploymentUrl).createAuthor();
@@ -146,7 +480,6 @@ public class ImsQTI21Test {
 			.answerSingleChoice("Right")
 			.saveAnswer()
 			.endTest()
-			.closeTest()
 			.assertOnCourseAttempts(1)
 			.assertOnCourseAssessmentTestScore(1);
 	}
@@ -233,7 +566,6 @@ public class ImsQTI21Test {
 			.answerSingleChoice("Right")
 			.saveAnswer()
 			.endTest()
-			.closeTest()
 			.assertOnAssessmentResults()
 			.closeAssessmentResults()
 			.assertOnCourseAttempts(1)
@@ -278,8 +610,7 @@ public class ImsQTI21Test {
 			.answerHotspot("circle")
 			.saveAnswer()
 			.assertFeedback("Correct!")
-			.endTest()
-			.closeTest();
+			.endTest();
 		//check the results
 		qtiPage
 			.assertOnAssessmentResults()
@@ -355,8 +686,7 @@ public class ImsQTI21Test {
 			.answerCorrectKPrim("Deutschland", "Uruguay")
 			.answerIncorrectKPrim("Frankreich", "Spanien")
 			.saveAnswer()
-			.endTest()
-			.closeTest();
+			.endTest();
 		
 		//check the results
 		qtiPage
diff --git a/src/test/java/org/olat/selenium/UserTest.java b/src/test/java/org/olat/selenium/UserTest.java
index 128900bb7e5fa2cec035f4207c79665637c99a4d..ed244bacfbef0741f42349a22f00f9c9255cd3d6 100644
--- a/src/test/java/org/olat/selenium/UserTest.java
+++ b/src/test/java/org/olat/selenium/UserTest.java
@@ -34,7 +34,6 @@ import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.arquillian.test.api.ArquillianResource;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 import org.junit.Assert;
-import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.olat.restapi.support.vo.CourseVO;
@@ -51,8 +50,8 @@ import org.olat.selenium.page.user.PortalPage;
 import org.olat.selenium.page.user.UserAdminPage;
 import org.olat.selenium.page.user.UserPasswordPage;
 import org.olat.selenium.page.user.UserPreferencesPageFragment;
-import org.olat.selenium.page.user.UserProfilePage;
 import org.olat.selenium.page.user.UserPreferencesPageFragment.ResumeOption;
+import org.olat.selenium.page.user.UserProfilePage;
 import org.olat.selenium.page.user.UserToolsPage;
 import org.olat.selenium.page.user.VisitingCardPage;
 import org.olat.test.ArquillianDeployments;
@@ -62,7 +61,6 @@ import org.olat.user.restapi.UserVO;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
-import org.openqa.selenium.firefox.FirefoxDriver;
 
 /**
  * 
@@ -581,9 +579,6 @@ public class UserTest {
 	@RunAsClient
 	public void browserBack(@InitialPage LoginPage loginPage)
 	throws IOException, URISyntaxException {
-		
-		Assume.assumeTrue(browser instanceof FirefoxDriver);
-		
 		loginPage
 			.loginAs("administrator", "openolat")
 			.resume();
diff --git a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
index 2311aeda4b0f01eae1a4eecd3fca309b4c26311a..110c4d33bb0884299c4bcb09f966d317681af072 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
@@ -69,29 +69,31 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page startTestPart() {
+		By startBy = By.xpath("//button[contains(@onclick,'advanceTestPart')]");
+		browser.findElement(startBy).click();
+		OOGraphene.waitBusy(browser);
+		By menuBy = By.id("o_qti_menu");
+		OOGraphene.waitElement(menuBy, 5, browser);
+		return this;
+	}
+	
 	public QTI21Page assertOnAssessmentItem() {
 		By assessmentItemBy = By.cssSelector("div.qtiworks.o_assessmentitem.o_assessmenttest");
 		OOGraphene.waitElement(assessmentItemBy, 5, browser);
 		return this;
 	}
 	
-	//TODO still qti 1.2
-	public QTI21Page selectItem(int position) {
-		By itemsBy = By.cssSelector("a.o_sel_qti_menu_item");
-		List<WebElement> itemList = browser.findElements(itemsBy);
-		Assert.assertTrue(itemList.size() > position);
-		WebElement itemEl = itemList.get(position);
-		itemEl.click();
-		OOGraphene.waitBusy(browser);
+	public QTI21Page assertOnAssessmentItem(String title) {
+		By itemTitleBy = By.xpath("//div[@class='o_assessmentitem_wrapper']/h4[contains(normalize-space(.),'" + title + "')]");
+		OOGraphene.waitElement(itemTitleBy, 5, browser);
 		return this;
 	}
 	
-	public QTI21Page answerSingleChoice(int selectPosition) {
-		By itemsBy = By.cssSelector("div.choiceInteraction input[type='radio']");
-		List<WebElement> optionList = browser.findElements(itemsBy);
-		Assert.assertTrue(optionList.size() > selectPosition);
-		WebElement optionEl = optionList.get(selectPosition);
-		optionEl.click();
+	public QTI21Page selectItem(String title) {
+		By itemBy = By.xpath("//div[@id='o_qti_menu']//li[contains(@class,'o_qti_menu_item')]//a[span[contains(normalize-space(.),'" + title + "')]]");
+		OOGraphene.waitElement(itemBy, 5, browser);
+		browser.findElement(itemBy).click();
 		OOGraphene.waitBusy(browser);
 		return this;
 	}
@@ -167,6 +169,10 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page endTestPart() {
+		return endTest();
+	}
+	
 	public QTI21Page endTest() {
 		By endBy = By.cssSelector("a.o_sel_end_testpart");
 		browser.findElement(endBy).click();
@@ -219,6 +225,18 @@ public class QTI21Page {
 		return this;
 	}
 	
+	/**
+	 * This check specifically if the metadata of the test are visible.
+	 * 
+	 * @param timeout
+	 * @return
+	 */
+	public QTI21Page assertOnAssessmentResults(int timeout) {
+		By resultsBy = By.cssSelector("div.o_sel_results_details");
+		OOGraphene.waitElement(resultsBy, timeout, browser);
+		return this;
+	}
+	
 	public QTI21Page assertOnCourseAssessmentTestScore(int score) {
 		By resultsBy = By.xpath("//div[contains(@class,'o_personal')]//tr[contains(@class,'o_score')]/td[contains(text(),'" + score + "')]");
 		OOGraphene.waitElement(resultsBy, 5, browser);
@@ -231,12 +249,54 @@ public class QTI21Page {
 		return this;
 	}
 	
+	public QTI21Page assertOnAssessmentTestPassed() {
+		By notPassedBy = By.cssSelector("div.o_sel_results_details tr.o_state.o_passed ");
+		OOGraphene.waitElement(notPassedBy, 5, browser);
+		return this;
+	}
+	
+	public QTI21Page assertOnAssessmentTestNotPassed() {
+		By notPassedBy = By.cssSelector("div.o_sel_results_details tr.o_state.o_failed ");
+		OOGraphene.waitElement(notPassedBy, 5, browser);
+		return this;
+	}
+	
 	public QTI21Page assertOnAssessmentTestMaxScore(int score) {
 		By resultsBy = By.xpath("//div[contains(@class,'o_sel_results_details')]//tr[contains(@class,'o_sel_assessmenttest_maxscore')]/td[contains(text(),'" + score + "')]");
 		OOGraphene.waitElement(resultsBy, 5, browser);
 		return this;
 	}
 	
+	public QTI21Page assertOnAssessmentTestFeedback(String feedback) {
+		By feedbackBy = By.xpath("//div[contains(@class,'o_info')]/h3[contains(text(),'" + feedback + "')]");
+		OOGraphene.waitElement(feedbackBy, 5, browser);
+		List<WebElement> feedbackEls = browser.findElements(feedbackBy);
+		Assert.assertEquals(1, feedbackEls.size());
+		return this;
+	}
+	
+	/**
+	 * Check if the assessment terminated message is visible.
+	 * 
+	 * @return Itself
+	 */
+	public QTI21Page assertOnAssessmentTestTerminated() {
+		By terminatedBy = By.cssSelector("div.o_sel_assessment_test_terminated");
+		OOGraphene.waitElement(terminatedBy, 5, browser);
+		return this;
+	}
+	
+	/**
+	 * Check if the assessment terminated message is visible.
+	 * 
+	 * @return Itself
+	 */
+	public QTI21Page assertOnAssessmentTestTerminated(int timeout) {
+		By terminatedBy = By.cssSelector("div.o_sel_assessment_test_terminated");
+		OOGraphene.waitElement(terminatedBy, timeout, browser);
+		return this;
+	}
+	
 	/**
 	 * Yes in a dialog box controller.
 	 */
diff --git a/src/test/java/org/olat/test/file_resources/qti21/test_parts_without_feedbacks.zip b/src/test/java/org/olat/test/file_resources/qti21/test_parts_without_feedbacks.zip
new file mode 100644
index 0000000000000000000000000000000000000000..b234b7db61a3d18481d2d15f980054b6e7a8ccd5
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/test_parts_without_feedbacks.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/test_time_limits.zip b/src/test/java/org/olat/test/file_resources/qti21/test_time_limits.zip
new file mode 100644
index 0000000000000000000000000000000000000000..539d85c0a4807d87eb6ffcfea977937e428824fe
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/test_time_limits.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/test_with_feedbacks.zip b/src/test/java/org/olat/test/file_resources/qti21/test_with_feedbacks.zip
new file mode 100644
index 0000000000000000000000000000000000000000..630b9e52df65a0eb1300550173d4ece8921c6bc5
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/test_with_feedbacks.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/test_with_parts_and_test_feedbacks.zip b/src/test/java/org/olat/test/file_resources/qti21/test_with_parts_and_test_feedbacks.zip
new file mode 100644
index 0000000000000000000000000000000000000000..4cf9fcd0a1d93f52da699f72d142ec7323dcf448
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/test_with_parts_and_test_feedbacks.zip differ
diff --git a/src/test/java/org/olat/test/file_resources/qti21/test_without_feedbacks.zip b/src/test/java/org/olat/test/file_resources/qti21/test_without_feedbacks.zip
new file mode 100644
index 0000000000000000000000000000000000000000..eb9cd0d4e5b287eff47d9e39fa93593005ac571b
Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/qti21/test_without_feedbacks.zip differ