diff --git a/src/main/java/org/olat/ims/qti21/manager/AssessmentResponseDAO.java b/src/main/java/org/olat/ims/qti21/manager/AssessmentResponseDAO.java
index e2e5800211ebec77bd9e042656ff2c6d844682a2..63fd36db8c7e972807222e52a12f295bc933fadc 100644
--- a/src/main/java/org/olat/ims/qti21/manager/AssessmentResponseDAO.java
+++ b/src/main/java/org/olat/ims/qti21/manager/AssessmentResponseDAO.java
@@ -104,7 +104,7 @@ public class AssessmentResponseDAO {
 		  .append(" where testSession.repositoryEntry.key=:repoEntryKey")
 		  .append("  and testSession.testEntry.key=:testEntryKey")
 		  .append("  and testSession.subIdent=:subIdent")
-		  .append("  and testSession.terminationTime is not null")
+		  .append("  and testSession.finishTime is not null")
 		  .append("  and (");
 		if(users) {
 			sb.append(" testSession.identity.key is not null");
@@ -141,7 +141,7 @@ public class AssessmentResponseDAO {
 		  .append(" left join assessmentEntry.identity as ident")
 		  .append(" left join ident.user as usr")
 		  .append(" where testSession.testEntry.key=:testEntryKey")
-		  .append("  and testSession.terminationTime is not null");
+		  .append("  and testSession.finishTime is not null");
 		if(courseEntry != null) {
 			sb.append(" and testSession.repositoryEntry.key=:repoEntryKey");
 		}
diff --git a/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java b/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
index 7d2fc828375c71cc49da93e80efe5869b217c6ef..3d613327b1a729a0c62605e814385baaaae7a81c 100644
--- a/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
+++ b/src/main/java/org/olat/ims/qti21/manager/AssessmentTestSessionDAO.java
@@ -335,7 +335,7 @@ public class AssessmentTestSessionDAO {
 		  .append(" left join fetch testEntry.olatResource testResource")
 		  .append(" inner join fetch session.identity assessedIdentity")
 		  .append(" inner join fetch assessedIdentity.user assessedUser")
-		  .append(" where session.repositoryEntry.key=:repositoryEntryKey and session.terminationTime is null and session.testEntry.key=:testEntryKey");
+		  .append(" where session.repositoryEntry.key=:repositoryEntryKey and (session.finishTime is null or session.terminationTime is null) and session.testEntry.key=:testEntryKey");
 		if(StringHelper.containsNonWhitespace(courseSubIdent)) {
 			sb.append(" and session.subIdent=:subIdent");
 		} else {
@@ -357,7 +357,7 @@ public class AssessmentTestSessionDAO {
 		sb.append("select session.key from qtiassessmenttestsession session")
 		  .append(" left join session.testEntry testEntry")
 		  .append(" left join testEntry.olatResource testResource")
-		  .append(" where session.repositoryEntry.key=:repositoryEntryKey and session.terminationTime is null and session.testEntry.key=:testEntryKey");
+		  .append(" where session.repositoryEntry.key=:repositoryEntryKey and (session.finishTime is null or session.terminationTime is null) and session.testEntry.key=:testEntryKey");
 		if(StringHelper.containsNonWhitespace(courseSubIdent)) {
 			sb.append(" and session.subIdent=:subIdent");
 		} else {
diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
index 999e31413371c1833d7fc74046f7a8d2f155e8c1..9f657ab58eaf3516a1a5bb9e9fbdf6b501b3eb38 100644
--- a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
+++ b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
@@ -80,7 +80,7 @@ public class QTI21StatisticsManagerImpl implements QTI21StatisticsManager {
 	@Autowired
 	private DB dbInstance;
 	
-	private StringBuilder decorateRSet(StringBuilder sb, QTI21StatisticSearchParams searchParams, boolean terminated) {
+	private StringBuilder decorateRSet(StringBuilder sb, QTI21StatisticSearchParams searchParams, boolean finished) {
 		sb.append(" where asession.testEntry.key=:testEntryKey and asession.repositoryEntry.key=:repositoryEntryKey");
 		if(searchParams.getNodeIdent() != null ) {
 			sb.append(" and asession.subIdent=:subIdent");
@@ -88,8 +88,8 @@ public class QTI21StatisticsManagerImpl implements QTI21StatisticsManager {
 			sb.append(" and asession.subIdent is null");
 		}
 
-		if(terminated) {
-			sb.append(" and asession.terminationTime is not null");
+		if(finished) {
+			sb.append(" and asession.finishTime is not null");
 		}
 		
 		sb.append(" and asession.lastModified = (select max(a2session.lastModified) from qtiassessmenttestsession a2session")
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 bd4eb0460497e2b8ef831ef253efdcbbe64cb797..ef788e3d07cf92f1b37bffc80cb54caf57b00e2f 100644
--- a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java
@@ -155,7 +155,7 @@ public class AssessmentTestDisplayController extends BasicController implements
 	private AssessmentResultController resultCtrl;
 	private TestSessionController testSessionController;
 
-	private DialogBoxController advanceTestPartDialog;
+	private DialogBoxController advanceTestPartDialog, endTestPartDialog;
 	private DialogBoxController confirmCancelDialog;
 	private DialogBoxController confirmSuspendDialog;
 	
@@ -354,6 +354,11 @@ public class AssessmentTestDisplayController extends BasicController implements
 				processAdvanceTestPart(ureq);
 			}
 			mainVC.setDirty(true);
+		} else if(endTestPartDialog == source) {
+			if(DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) {
+				processEndTestPart(ureq);
+			}
+			mainVC.setDirty(true);
 		} else if(confirmCancelDialog == source) {
 			if(DialogBoxUIFactory.isOkEvent(event) || DialogBoxUIFactory.isYesEvent(event)) {
 				doCancel(ureq);
@@ -476,7 +481,7 @@ public class AssessmentTestDisplayController extends BasicController implements
 				handleResponse(ureq, qe.getStringResponseMap(), qe.getFileResponseMap(), qe.getComment());
 				break;
 			case endTestPart:
-				processEndTestPart(ureq);
+				confirmEndTestPart(ureq);
 				break;
 			case advanceTestPart:
 				confirmAdvanceTestPart(ureq);
@@ -845,12 +850,40 @@ public class AssessmentTestDisplayController extends BasicController implements
         	itemSession.setPassed(pass);
         }
     }
+	
+	private void confirmEndTestPart(UserRequest ureq) {
+		TestPlanNode nextTestPart = testSessionController.findNextEnterableTestPart();
+
+		if(nextTestPart == null) {
+			String title = translate("confirm.close.test.title");
+			String text = translate("confirm.close.test.text");
+			endTestPartDialog = activateOkCancelDialog(ureq, title, text, endTestPartDialog);
+		} else {
+			TestPart currentTestPart = testSessionController.getCurrentTestPart();
+			if(currentTestPart == null) {
+				processEndTestPart(ureq);
+			} else {
+				String title = translate("confirm.end.testpart.title");
+				String text = translate("confirm.end.testpart.text");
+				endTestPartDialog = activateOkCancelDialog(ureq, title, text, endTestPartDialog);
+			}
+		}
+	}
 
 	//public CandidateSession endCurrentTestPart(final CandidateSessionContext candidateSessionContext)
 	private void processEndTestPart(UserRequest ureq) {
 		 /* Update state */
         final Date requestTimestamp = ureq.getRequestTimestamp();
         testSessionController.endCurrentTestPart(requestTimestamp);
+        
+        TestSessionState testSessionState = testSessionController.getTestSessionState();
+        
+        // Record current result state
+	    final AssessmentResult assessmentResult = computeAndRecordTestAssessmentResult(ureq, testSessionState, false);
+        
+        if(testSessionController.findNextEnterableTestPart() == null) {
+        	candidateSession = qtiService.finishTestSession(candidateSession, testSessionState, assessmentResult, requestTimestamp);
+        }
 	}
 	
 	/**
diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21TestSessionTableModel.java b/src/main/java/org/olat/ims/qti21/ui/QTI21TestSessionTableModel.java
index a14a76ed41cbd7e8c840ae1aea95a7989039807d..a629e1759b64bab5637e2ac905b6efcdf3d0cb61 100644
--- a/src/main/java/org/olat/ims/qti21/ui/QTI21TestSessionTableModel.java
+++ b/src/main/java/org/olat/ims/qti21/ui/QTI21TestSessionTableModel.java
@@ -61,20 +61,20 @@ public class QTI21TestSessionTableModel extends DefaultFlexiTableDataModel<Asses
 		switch(TSCols.values()[col]) {
 			case lastModified: return session.getLastModified();
 			case duration: {
-				if(session.getTerminationTime() != null) {
+				if(session.getFinishTime() != null) {
 					return Formatter.formatDuration(session.getDuration().longValue());
 				}
 				return "<span class='o_ochre'>" + translator.translate("assessment.test.open") + "</span>";
 			}
 			case results: {
-				if(session.getTerminationTime() != null) {
+				if(session.getFinishTime() != null) {
 					return AssessmentHelper.getRoundedScore(session.getScore());
 				}
 				return "<span class='o_ochre'>" + translator.translate("assessment.test.notReleased") + "</span>";
 			}
 			case open: {
-				Date terminated = session.getTerminationTime();
-				return terminated == null ? Boolean.FALSE : Boolean.TRUE;
+				Date finished = session.getFinishTime();
+				return finished == null ? Boolean.FALSE : Boolean.TRUE;
 			}
 			case correction: {
 				return (lastSession != null && lastSession.equals(session));
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/IdentitiesAssessmentTestCorrectionController.java b/src/main/java/org/olat/ims/qti21/ui/assessment/IdentitiesAssessmentTestCorrectionController.java
index 6ad9e3b2e058f980b89cb5ed97d22321d4d39401..b6d6b4708bb3fb027317d1eaaacdbf4390235d25 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/IdentitiesAssessmentTestCorrectionController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/IdentitiesAssessmentTestCorrectionController.java
@@ -237,15 +237,15 @@ public class IdentitiesAssessmentTestCorrectionController extends BasicControlle
 				continue;
 			}
 			
-			Date tDate = session.getTerminationTime();
-			if(tDate == null) {
+			Date fDate = session.getFinishTime();
+			if(fDate == null) {
 				//not terminated
 			} else {
 				if(identityToSessions.containsKey(assessedIdentity)) {
 					AssessmentTestSession currentSession = identityToSessions.get(assessedIdentity);
 
-					Date currentTDate = currentSession.getTerminationTime();
-					if(tDate.after(currentTDate)) {
+					Date currentFDate = currentSession.getFinishTime();
+					if(fDate.after(currentFDate)) {
 						identityToSessions.put(assessedIdentity, session);
 					}
 				} else {
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestAndTestPartOptionsEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestAndTestPartOptionsEditorController.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b33d7ed6bb1f3955e3aecdaddb279d95992a1d0
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestAndTestPartOptionsEditorController.java
@@ -0,0 +1,180 @@
+/**
+ * <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.ui.editor;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.util.StringHelper;
+import org.olat.course.assessment.AssessmentHelper;
+import org.olat.ims.qti21.model.xml.AssessmentTestBuilder;
+import org.olat.ims.qti21.ui.editor.events.AssessmentTestEvent;
+
+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.TestPart;
+
+/**
+ * 
+ * Initial date: 22.05.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentTestAndTestPartOptionsEditorController extends ItemSessionControlController {
+
+	private static final String[] yesnoKeys = new String[] { "y", "n" };
+	private static final String[] navigationKeys = new String[]{
+			NavigationMode.LINEAR.name(), NavigationMode.NONLINEAR.name()
+	};
+	
+	private TextElement titleEl, maxScoreEl, cutValueEl;
+	private SingleSelection exportScoreEl, navigationModeEl;
+
+	private final TestPart testPart;
+	private final AssessmentTest assessmentTest;
+	private final AssessmentTestBuilder testBuilder;
+	
+	public AssessmentTestAndTestPartOptionsEditorController(UserRequest ureq, WindowControl wControl,
+			AssessmentTest assessmentTest, TestPart testPart, AssessmentTestBuilder testBuilder, boolean restrictedEdit) {
+		super(ureq, wControl, testPart, restrictedEdit);
+		this.assessmentTest = assessmentTest;
+		this.testBuilder = testBuilder;
+		this.testPart = testPart;
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		setFormContextHelp("Test and Questionnaire Editor in Detail#details_testeditor_test_konf");
+		
+		String title = assessmentTest.getTitle();
+		titleEl = uifactory.addTextElement("title", "form.metadata.title", 255, title, formLayout);
+		titleEl.setMandatory(true);
+		
+		//export score
+		String[] yesnoValues = new String[] { translate("yes"), translate("no") };
+		exportScoreEl = uifactory.addRadiosHorizontal("form.test.export.score", formLayout, yesnoKeys, yesnoValues);
+		exportScoreEl.setEnabled(!restrictedEdit);
+		if(testBuilder.isExportScore()) {
+			exportScoreEl.select(yesnoKeys[0], true);
+		} else {
+			exportScoreEl.select(yesnoKeys[1], false);
+		}
+		
+		//score
+		String maxScore = testBuilder.getMaxScore() == null ? "" : AssessmentHelper.getRoundedScore(testBuilder.getMaxScore());
+		maxScoreEl = uifactory.addTextElement("max.score", "max.score", 8, maxScore, formLayout);
+		maxScoreEl.setEnabled(false);
+		
+		Double cutValue = testBuilder.getCutValue();
+		String cutValueStr = cutValue == null ? "" : cutValue.toString();
+		cutValueEl = uifactory.addTextElement("cut.value", "cut.value", 8, cutValueStr, formLayout);
+		cutValueEl.setEnabled(!restrictedEdit);
+		
+		uifactory.addSpacerElement("space-test-part", formLayout, false);
+		
+		String[] navigationValues = new String[] {
+				translate("form.testPart.navigationMode.linear"), translate("form.testPart.navigationMode.nonlinear")
+		};
+		String mode = testPart.getNavigationMode() == null ? NavigationMode.LINEAR.name() : testPart.getNavigationMode().name();
+		navigationModeEl = uifactory.addRadiosHorizontal("navigationMode", "form.testPart.navigationMode", formLayout, navigationKeys, navigationValues);
+		navigationModeEl.select(mode, true);
+		navigationModeEl.setEnabled(!restrictedEdit);
+		
+		super.initForm(formLayout, listener, ureq);
+		
+		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		formLayout.add(buttonsCont);
+		uifactory.addFormSubmitButton("save", "save", buttonsCont);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	public String getTitle() {
+		return titleEl.getValue();
+	}
+
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = true;
+
+		titleEl.clearError();
+		if(!StringHelper.containsNonWhitespace(titleEl.getValue())) {
+			titleEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		}
+		
+		cutValueEl.clearError();
+		if(StringHelper.containsNonWhitespace(cutValueEl.getValue())) {
+			String cutValue = cutValueEl.getValue();
+			try {
+				double val = Double.parseDouble(cutValue);
+				if(val < 0.0) {
+					cutValueEl.setErrorKey("form.error.nointeger", null);
+					allOk &= false;
+				}
+			} catch (NumberFormatException e) {
+				cutValueEl.setErrorKey("form.error.nointeger", null);
+				allOk &= false;
+			}
+		}
+		
+		navigationModeEl.clearError();
+		if(!navigationModeEl.isOneSelected()) {
+			navigationModeEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		}
+		
+		return allOk & super.validateFormLogic(ureq);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		super.formOK(ureq);
+		
+		String title = titleEl.getValue();
+		assessmentTest.setTitle(title);
+		
+		testBuilder.setExportScore(exportScoreEl.isOneSelected() && exportScoreEl.isSelected(0));
+		
+		String cutValue = cutValueEl.getValue();
+		if(StringHelper.containsNonWhitespace(cutValue)) {
+			testBuilder.setCutValue(new Double(cutValue));
+		} else {
+			testBuilder.setCutValue(null);
+		}
+		
+		// navigation mode
+		if(navigationModeEl.isOneSelected() && navigationModeEl.isSelected(0)) {
+			testPart.setNavigationMode(NavigationMode.LINEAR);
+		} else {
+			testPart.setNavigationMode(NavigationMode.NONLINEAR);
+		}
+		
+		fireEvent(ureq, AssessmentTestEvent.ASSESSMENT_TEST_CHANGED_EVENT);
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
index 7e8c19407c0d00828349d0704d64cf696c9f990a..de81eb6ab3c5462c77132867b0d88c2d2dd5c1e3 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestComposerController.java
@@ -906,7 +906,9 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 
 		Object uobject = selectedNode.getUserObject();
 		if(uobject instanceof AssessmentTest) {
-			currentEditorCtrl = new AssessmentTestEditorController(ureq, getWindowControl(), assessmentTestBuilder, restrictedEdit);
+			AssessmentTest test = (AssessmentTest)uobject;
+			TestPart uniqueTestPart = test.getTestParts().size() == 1 ? test.getTestParts().get(0) : null;
+			currentEditorCtrl = new AssessmentTestEditorController(ureq, getWindowControl(), assessmentTestBuilder, uniqueTestPart, restrictedEdit);
 		} else if(uobject instanceof TestPart) {
 			currentEditorCtrl = new AssessmentTestPartEditorController(ureq, getWindowControl(), (TestPart)uobject, restrictedEdit);
 		} else if(uobject instanceof AssessmentSection) {
@@ -930,8 +932,16 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		}
 		
 		if(deleteLink != null) {
-			deleteLink.setEnabled(uobject instanceof AssessmentSection || uobject instanceof AssessmentItemRef);
+			if(uobject instanceof AssessmentSection || uobject instanceof AssessmentItemRef) {
+				deleteLink.setEnabled(true);
+			} else if(uobject instanceof TestPart) {
+				TestPart testPart = (TestPart)uobject;
+				deleteLink.setEnabled(testPart.getParent().getTestParts().size() > 1);
+			} else {
+				deleteLink.setEnabled(false);
+			}
 		}
+		
 		if(copyLink != null) {
 			copyLink.setEnabled(uobject instanceof AssessmentItemRef);
 		}
@@ -1002,7 +1012,14 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 		if(uobject instanceof AssessmentTest) {
 			showWarning("error.cannot.delete");
 		} else if(uobject instanceof TestPart) {
-			showWarning("error.cannot.delete");
+			TestPart testPart = (TestPart)uobject;
+			if(testPart.getParent().getTestParts().size() == 1) {
+				showWarning("error.cannot.delete");
+			}
+			
+			String msg = translate("delete.testPart");
+			confirmDeleteCtrl = activateYesNoDialog(ureq, translate("tools.change.delete"), msg, confirmDeleteCtrl);
+			confirmDeleteCtrl.setUserObject(selectedNode);
 		} else {
 			String msg;
 			if(uobject instanceof AssessmentSection) {
@@ -1021,7 +1038,9 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 	
 	private void doDelete(UserRequest ureq, TreeNode selectedNode) {
 		Object uobject = selectedNode.getUserObject();
-		if(uobject instanceof AssessmentSection) {
+		if(uobject instanceof TestPart) {
+			doDeleteTestPart((TestPart)uobject);
+		} else if(uobject instanceof AssessmentSection) {
 			doDeleteAssessmentSection((AssessmentSection)uobject);
 		} else if(uobject instanceof AssessmentItemRef) {
 			doDeleteAssessmentItemRef((AssessmentItemRef)uobject);
@@ -1082,6 +1101,14 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
 			assessmentSection.getParent().getChildAbstractParts().remove(assessmentSection);
 		}
 	}
+	
+	private void doDeleteTestPart(TestPart testPart) {
+		List<AssessmentSection> sections = new ArrayList<>(testPart.getAssessmentSections());
+		for(AssessmentSection section:sections) {
+			doDeleteAssessmentSection(section);
+		}
+		testPart.getParent().getTestParts().remove(testPart);
+	}
 
 	private ResourceType getResourceType(AssessmentItemRef itemRef) {
 		return getResourceType(manifestBuilder, itemRef);
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorAndComposerTreeModel.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorAndComposerTreeModel.java
index b8187d602c6722ace54cc2de4181213c0e44f92b..4b37cfad01669e333fd54a3cf7e14f21c00c1e40 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorAndComposerTreeModel.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorAndComposerTreeModel.java
@@ -61,9 +61,17 @@ public class AssessmentTestEditorAndComposerTreeModel extends GenericTreeModel i
 		
 		//list all test parts
 		List<TestPart> parts = test.getChildAbstractParts();
-		int counter = 0;
-		for(TestPart part:parts) {
-			buildRecursively(part, ++counter, node);
+		if(parts.size() == 1) {
+			List<AssessmentSection> sections = parts.get(0).getAssessmentSections();
+			for(AssessmentSection section:sections) {
+				buildRecursively(section, node);
+			}
+			
+		} else {
+			int counter = 0;
+			for(TestPart part:parts) {
+				buildRecursively(part, ++counter, node);
+			}
 		}
 	}
 	
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorController.java b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorController.java
index aea0b22104db4df62dea7ea4d3471a449e14489b..3a88ebd22bee69a0022314a348b0d8cfd2e8bf9b 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/AssessmentTestEditorController.java
@@ -34,6 +34,7 @@ import org.olat.ims.qti21.ui.AssessmentTestDisplayController;
 import org.olat.ims.qti21.ui.editor.events.AssessmentTestEvent;
 
 import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
+import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
 
 /**
  * 
@@ -46,17 +47,19 @@ public class AssessmentTestEditorController extends BasicController {
 	private final TabbedPane tabbedPane;
 	private final VelocityContainer mainVC;
 	
-	private AssessmentTestOptionsEditorController optionsCtrl;
+	private Controller optionsCtrl;
 	private AssessmentTestFeedbackEditorController feedbackCtrl;
 	
 	private final boolean restrictedEdit;
+	private final TestPart testPart;
 	private final AssessmentTest assessmentTest;
 	private final AssessmentTestBuilder testBuilder;
 	
 	public AssessmentTestEditorController(UserRequest ureq, WindowControl wControl,
-			AssessmentTestBuilder testBuilder, boolean restrictedEdit) {
+			AssessmentTestBuilder testBuilder, TestPart testPart, boolean restrictedEdit) {
 		super(ureq, wControl, Util.createPackageTranslator(AssessmentTestDisplayController.class, ureq.getLocale()));
 		this.testBuilder = testBuilder;
+		this.testPart = testPart;
 		this.assessmentTest = testBuilder.getAssessmentTest();
 		this.restrictedEdit = restrictedEdit;
 		
@@ -77,8 +80,13 @@ public class AssessmentTestEditorController extends BasicController {
 	
 	private void initTestEditor(UserRequest ureq) {
 		if(QTI21Constants.TOOLNAME.equals(assessmentTest.getToolName())) {
-			optionsCtrl = new AssessmentTestOptionsEditorController(ureq, getWindowControl(), assessmentTest, testBuilder, restrictedEdit);
+			if(testPart != null) {
+				optionsCtrl = new AssessmentTestAndTestPartOptionsEditorController(ureq, getWindowControl(), assessmentTest, testPart, testBuilder, restrictedEdit);
+			} else {
+				optionsCtrl = new AssessmentTestOptionsEditorController(ureq, getWindowControl(), assessmentTest, testBuilder, restrictedEdit);
+			}
 			listenTo(optionsCtrl);
+			
 			feedbackCtrl = new AssessmentTestFeedbackEditorController(ureq, getWindowControl(), testBuilder, restrictedEdit);
 			listenTo(feedbackCtrl);
 			
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/ItemSessionControlController.java b/src/main/java/org/olat/ims/qti21/ui/editor/ItemSessionControlController.java
index e7fa1c10f7b2d993ec884dd82b6df86eb5c5d1c3..cca1f464bcdfc27ccc0e185680b945701908fb31 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/ItemSessionControlController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/ItemSessionControlController.java
@@ -48,7 +48,7 @@ public abstract class ItemSessionControlController extends FormBasicController {
 	private static final String[] attemtpsKeys = new String[] { "y", "n", "inherit" };
 
 	private TextElement maxAttemptsEl /*, maxTimeEl */;
-	private SingleSelection limitAttemptsEl, allowCommentEl, showSolutionEl;
+	private SingleSelection limitAttemptsEl, allowCommentEl, allowReviewEl, showSolutionEl;
 	
 	protected final boolean restrictedEdit;
 	private final AbstractPart part;
@@ -112,6 +112,15 @@ public abstract class ItemSessionControlController extends FormBasicController {
 		} else {
 			allowCommentEl.select(yesnoKeys[1], false);
 		}
+		
+		allowReviewEl = uifactory.addRadiosHorizontal("item.session.control.allow.review", formLayout, yesnoKeys, yesnoValues);
+		allowReviewEl.addActionListener(FormEvent.ONCHANGE);
+		allowReviewEl.setEnabled(!restrictedEdit);
+		if(itemSessionControl != null && itemSessionControl.getAllowReview() != null && itemSessionControl.getAllowReview().booleanValue()) {
+			allowReviewEl.select(yesnoKeys[0], true);
+		} else {
+			allowReviewEl.select(yesnoKeys[1], false);
+		}
 	
 		showSolutionEl = uifactory.addRadiosHorizontal("item.session.control.show.solution", formLayout, yesnoKeys, yesnoValues);
 		showSolutionEl.addActionListener(FormEvent.ONCHANGE);
@@ -138,6 +147,12 @@ public abstract class ItemSessionControlController extends FormBasicController {
 			allOk &= false;
 		}
 		
+		allowReviewEl.clearError();
+		if(!allowReviewEl.isOneSelected()) {
+			allowReviewEl.setErrorKey("form.legende.mandatory", null);
+			allOk &= false;
+		}
+		
 		showSolutionEl.clearError();
 		if(!showSolutionEl.isOneSelected()) {
 			showSolutionEl.setErrorKey("form.legende.mandatory", null);
@@ -196,6 +211,12 @@ public abstract class ItemSessionControlController extends FormBasicController {
 			itemSessionControl.setAllowComment(Boolean.FALSE);
 		}
 		
+		if(allowReviewEl.isOneSelected() && allowReviewEl.isSelected(0)) {
+			checkNotNull(itemSessionControl).setAllowReview(Boolean.TRUE);
+		} else if(itemSessionControl != null) {
+			itemSessionControl.setAllowReview(Boolean.FALSE);
+		}
+		
 		if(showSolutionEl.isOneSelected() && showSolutionEl.isSelected(0)) {
 			checkNotNull(itemSessionControl).setShowSolution(Boolean.TRUE);
 		} else if(itemSessionControl != null) {
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
index 3c246253b8633d1ee7a5da3776ea05bb0ab3d116..d1ec0954b0be2b48cfab3eff70def81c8a2910f4 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
@@ -5,6 +5,7 @@ correct.answers=Korrekt
 cut.value=Notwendige Punktzahl f\u00FCr "Bestanden"
 delete.item=$org.olat.ims.qti.editor\:delete.item
 delete.section=$org.olat.ims.qti.editor\:delete.section
+delete.testPart=Wollen Sie das Test Part mit all ihren Fragen wirklich l\u00F6schen?
 editor.sc.title=Single choice
 editor.unkown.title=Unbekanntes interaction
 error.cannot.create.section=Sie k\u00F6nnen nicht eine Sektion hier erstellen.
@@ -87,6 +88,7 @@ form.testPart.navigationMode.linear=Linear
 form.testPart.navigationMode.nonlinear=Nicht linear
 form.unkown=Unbekannt
 item.session.control.allow.comment=Kommentar erlauben
+item.session.control.allow.review=Review erlauben
 item.session.control.attempts=Versuch
 item.session.control.show.solution=L\u00F6sung anzeigen
 max.score=Maximal erreichbare Punktzahl
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
index 6e7bacd7ee7190e6aa2174cfeb07f2a84b5406cc..ebbec1a65fa074fa8718475be3c8bcc5e728309f 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
@@ -5,6 +5,7 @@ correct.answers=Correct
 cut.value=Cut value
 delete.item=$org.olat.ims.qti.editor\:delete.item
 delete.section=$org.olat.ims.qti.editor\:delete.section
+delete.testPart=Do you really want to delete the test part along with all its questions?
 editor.sc.title=Single choice
 editor.unkown.title=Unkown interaction
 error.cannot.create.section=A section cannot be created everywhere\!
@@ -87,6 +88,7 @@ form.testPart.navigationMode.nonlinear=Non linear
 form.unkown=Unkown
 inherit=Inherit
 item.session.control.allow.comment=Allow comments
+item.session.control.allow.review=Allow review of questions
 item.session.control.attempts=Attempts
 item.session.control.show.solution=Show solution
 max.score=Max. score
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 060a03139f06773047cfaf9798fa2dea90704b02..2d162861fbe794f6481c8460815ddf6eedb5f678 100644
--- a/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
+++ b/src/test/java/org/olat/selenium/page/qti/QTI21Page.java
@@ -170,6 +170,7 @@ public class QTI21Page {
 		By endBy = By.cssSelector("a.o_sel_end_testpart");
 		browser.findElement(endBy).click();
 		OOGraphene.waitBusy(browser);
+		confirm();
 		return this;
 	}
 	
@@ -177,12 +178,19 @@ public class QTI21Page {
 		By endBy = By.cssSelector("a.o_sel_close_test");
 		browser.findElement(endBy).click();
 		OOGraphene.waitBusy(browser);
-		
+		confirm();
+		return this;
+	}
+	
+	/**
+	 * Yes in a dialog box controller.
+	 */
+	private void confirm() {
 		// confirm
 		By confirmButtonBy = By.cssSelector("div.modal-dialog div.modal-footer a");
+		OOGraphene.waitElement(confirmButtonBy, 5, browser);
 		List<WebElement> buttonsEl = browser.findElements(confirmButtonBy);
 		buttonsEl.get(0).click();
 		OOGraphene.waitBusy(browser);
-		return this;
 	}
 }