diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8be897..82b20a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 # Changelog
 
 ## [Unreleased]
+### Added
+- Common Stack Trace frames skip in description and logs, by @HardNorth 
+- `@Issue` and `@Issues` annotations support, by @HardNorth
+### Changed
+- Client version updated on [5.2.20](https://github.com/reportportal/client-java/releases/tag/5.2.20), by @HardNorth
 
 ## [5.3.3]
 ### Added
diff --git a/build.gradle b/build.gradle
index 8613d4a..eb9ff15 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,7 +37,7 @@ repositories {
 }
 
 dependencies {
-    api 'com.epam.reportportal:client-java:5.2.14'
+    api 'com.epam.reportportal:client-java:5.2.20'
 
     compileOnly "org.junit.jupiter:junit-jupiter-api:${junit_version}"
     implementation 'org.slf4j:slf4j-api:2.0.7'
diff --git a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java
index 4b5a0da..a308e1d 100644
--- a/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java
+++ b/src/main/java/com/epam/reportportal/junit5/ReportPortalExtension.java
@@ -16,9 +16,7 @@
 
 package com.epam.reportportal.junit5;
 
-import com.epam.reportportal.annotations.Description;
-import com.epam.reportportal.annotations.ParameterKey;
-import com.epam.reportportal.annotations.TestCaseId;
+import com.epam.reportportal.annotations.*;
 import com.epam.reportportal.annotations.attribute.Attributes;
 import com.epam.reportportal.listeners.ItemStatus;
 import com.epam.reportportal.listeners.ListenerParameters;
@@ -27,16 +25,17 @@
 import com.epam.reportportal.service.item.TestCaseIdEntry;
 import com.epam.reportportal.service.tree.TestItemTree;
 import com.epam.reportportal.utils.AttributeParser;
+import com.epam.reportportal.utils.IssueUtils;
 import com.epam.reportportal.utils.ParameterUtils;
 import com.epam.reportportal.utils.TestCaseIdUtils;
-import com.epam.reportportal.utils.markdown.MarkdownUtils;
+import com.epam.reportportal.utils.formatting.MarkdownUtils;
 import com.epam.ta.reportportal.ws.model.*;
 import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ;
 import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ;
 import com.epam.ta.reportportal.ws.model.log.SaveLogRQ;
 import io.reactivex.Maybe;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.*;
 import org.junit.jupiter.api.extension.*;
 import org.opentest4j.TestAbortedException;
@@ -58,16 +57,16 @@
 import static com.epam.reportportal.junit5.utils.ItemTreeUtils.createItemTreeKey;
 import static com.epam.reportportal.listeners.ItemStatus.*;
 import static com.epam.reportportal.service.tree.TestItemTree.createTestItemLeaf;
+import static com.epam.reportportal.utils.formatting.ExceptionUtils.getStackTrace;
 import static java.util.Optional.of;
 import static java.util.Optional.ofNullable;
-import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;
 
 /*
  * ReportPortal Extension sends the results of test execution to ReportPortal in RealTime
  */
 public class ReportPortalExtension
-		implements Extension, BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, AfterTestExecutionCallback,
-				   AfterAllCallback, TestWatcher {
+		implements Extension, BeforeAllCallback, BeforeEachCallback, InvocationInterceptor, AfterTestExecutionCallback, AfterAllCallback,
+		           TestWatcher {
 
 	private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalExtension.class);
 
@@ -91,9 +90,10 @@ public class ReportPortalExtension
 	private static final Map<String, Launch> launchMap = new ConcurrentHashMap<>();
 	private final Map<ExtensionContext, Maybe<String>> idMapping = new ConcurrentHashMap<>();
 	private final Map<ExtensionContext, Maybe<String>> testTemplates = new ConcurrentHashMap<>();
+	private final Map<ExtensionContext, List<ParameterResource>> testParameters = new ConcurrentHashMap<>();
 	private final Set<ExtensionContext> failedClassInits = Collections.newSetFromMap(new ConcurrentHashMap<>());
-	public static final String DESCRIPTION_TEST_ERROR_FORMAT = "%s\nError: \n%s";
-	private final Map<ExtensionContext, Throwable> testThrowable = new ConcurrentHashMap<>();
+	public static final String DESCRIPTION_TEST_ERROR_FORMAT = "Error: \n%s";
+
 	@Nonnull
 	protected Optional<Maybe<String>> getItemId(@Nonnull ExtensionContext context) {
 		return ofNullable(idMapping.get(context));
@@ -137,7 +137,7 @@ protected StartLaunchRQ buildStartLaunchRq(ListenerParameters parameters) {
 		rq.setAttributes(attributes);
 		rq.setStartTime(Calendar.getInstance().getTime());
 		rq.setRerun(parameters.isRerun());
-		rq.setRerunOf(StringUtils.isEmpty(parameters.getRerunOf()) ? null : parameters.getRerunOf());
+		rq.setRerunOf(StringUtils.isNotBlank(parameters.getRerunOf()) ? parameters.getRerunOf() : null);
 		return rq;
 	}
 
@@ -220,21 +220,15 @@ public void beforeEach(ExtensionContext context) {
 	}
 
 	@Override
-	public void interceptBeforeAllMethod(Invocation<Void> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext parentContext) throws Throwable {
-		Maybe<String> id = startBeforeAfter(
-				invocationContext.getExecutable(),
-				parentContext,
-				parentContext,
-				BEFORE_CLASS
-		);
+	public void interceptBeforeAllMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext parentContext) throws Throwable {
+		Maybe<String> id = startBeforeAfter(invocationContext.getExecutable(), parentContext, parentContext, BEFORE_CLASS);
 		finishBeforeAll(invocation, invocationContext, parentContext, id);
 	}
 
 	@Override
-	public <T> T interceptTestClassConstructor(Invocation<T> invocation,
-											   ReflectiveInvocationContext<Constructor<T>> invocationContext,
-											   ExtensionContext parentContext) throws Throwable {
+	public <T> T interceptTestClassConstructor(Invocation<T> invocation, ReflectiveInvocationContext<Constructor<T>> invocationContext,
+			ExtensionContext parentContext) throws Throwable {
 		try {
 			return invocation.proceed();
 		} catch (Throwable cause) {
@@ -244,28 +238,23 @@ public <T> T interceptTestClassConstructor(Invocation<T> invocation,
 	}
 
 	@Override
-	public void interceptBeforeEachMethod(Invocation<Void> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext context) throws Throwable {
+	public void interceptBeforeEachMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext context) throws Throwable {
 		ExtensionContext parentContext = context.getParent().orElse(context.getRoot());
 		Maybe<String> id = startBeforeAfter(invocationContext.getExecutable(), parentContext, context, BEFORE_METHOD);
 		finishBeforeEach(invocation, invocationContext, context, id);
 	}
 
 	@Override
-	public void interceptAfterAllMethod(Invocation<Void> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext parentContext) throws Throwable {
-		Maybe<String> id = startBeforeAfter(
-				invocationContext.getExecutable(),
-				parentContext,
-				parentContext,
-				AFTER_CLASS
-		);
+	public void interceptAfterAllMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext parentContext) throws Throwable {
+		Maybe<String> id = startBeforeAfter(invocationContext.getExecutable(), parentContext, parentContext, AFTER_CLASS);
 		finishBeforeAfter(invocation, parentContext, id);
 	}
 
 	@Override
-	public void interceptAfterEachMethod(Invocation<Void> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext context) throws Throwable {
+	public void interceptAfterEachMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext context) throws Throwable {
 		ExtensionContext parentContext = context.getParent().orElse(context.getRoot());
 		Maybe<String> id = startBeforeAfter(invocationContext.getExecutable(), parentContext, context, AFTER_METHOD);
 		finishBeforeAfter(invocation, context, id);
@@ -279,8 +268,8 @@ public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocatio
 	}
 
 	@Override
-	public <T> T interceptTestFactoryMethod(Invocation<T> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
+	public <T> T interceptTestFactoryMethod(Invocation<T> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext extensionContext) throws Throwable {
 		startTestItem(extensionContext, invocationContext.getArguments(), SUITE);
 		return invocation.proceed();
 	}
@@ -288,23 +277,34 @@ public <T> T interceptTestFactoryMethod(Invocation<T> invocation,
 	/**
 	 * Returns a status of a test based on execution exception
 	 *
-	 * @param context JUnit's test context
+	 * @param context   JUnit's test context
 	 * @param throwable test exception
 	 * @return an {@link ItemStatus}
 	 */
+	@SuppressWarnings("unused")
 	@Nonnull
 	protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context, @Nullable final Throwable throwable) {
 		if (throwable == null) {
 			return PASSED;
 		}
-		testThrowable.put(context, throwable);
 		sendStackTraceToRP(throwable);
 		return IS_ASSUMPTION.test(throwable) ? SKIPPED : FAILED;
 	}
 
+	/**
+	 * Returns a status of a test based on whether or not it contains an execution exception
+	 *
+	 * @param context JUnit's test context
+	 * @return an {@link ItemStatus}
+	 */
+	@Nonnull
+	protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) {
+		return context.getExecutionException().map(t -> getExecutionStatus(context, t)).orElse(PASSED);
+	}
+
 	@Override
 	public void interceptDynamicTest(Invocation<Void> invocation, DynamicTestInvocationContext invocationContext,
-									 ExtensionContext extensionContext) throws Throwable {
+			ExtensionContext extensionContext) throws Throwable {
 		Optional<ExtensionContext> parent = extensionContext.getParent();
 		if (parent.map(p -> !idMapping.containsKey(p)).orElse(false)) {
 			List<ExtensionContext> parents = new ArrayList<>();
@@ -330,23 +330,12 @@ public void interceptDynamicTest(Invocation<Void> invocation, DynamicTestInvocat
 	}
 
 	@Override
-	public void interceptTestTemplateMethod(Invocation<Void> invocation,
-			ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
+	public void interceptTestTemplateMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext,
+			ExtensionContext extensionContext) throws Throwable {
 		startTestItem(extensionContext, invocationContext.getArguments(), STEP);
 		invocation.proceed();
 	}
 
-	/**
-	 * Returns a status of a test based on whether or not it contains an execution exception
-	 *
-	 * @param context JUnit's test context
-	 * @return an {@link ItemStatus}
-	 */
-	@Nonnull
-	protected ItemStatus getExecutionStatus(@Nonnull final ExtensionContext context) {
-		return context.getExecutionException().map(t -> getExecutionStatus(context, t)).orElse(PASSED);
-	}
-
 	@Override
 	public void afterTestExecution(ExtensionContext context) {
 		finishTemplates(context);
@@ -369,10 +358,9 @@ public void testDisabled(ExtensionContext context, Optional<String> reason) {
 	@Override
 	public void testFailed(ExtensionContext context, Throwable cause) {
 		context.getParent().ifPresent(parent -> {
-			if(failedClassInits.contains(parent)) {
+			if (failedClassInits.contains(parent)) {
 				startTestItem(context, STEP);
 				sendStackTraceToRP(cause);
-				testThrowable.put(context, cause);
 				finishTest(context, FAILED);
 			}
 		});
@@ -420,8 +408,7 @@ protected void finishBeforeEach(Invocation<Void> invocation, ReflectiveInvocatio
 		}
 	}
 
-	private void finishBeforeAfter(Invocation<Void> invocation, ExtensionContext context, Maybe<String> id)
-			throws Throwable {
+	private void finishBeforeAfter(Invocation<Void> invocation, ExtensionContext context, Maybe<String> id) throws Throwable {
 		try {
 			invocation.proceed();
 		} catch (Throwable throwable) {
@@ -475,30 +462,28 @@ protected void startTestItem(ExtensionContext context, List<Object> arguments, I
 	 * @param context     JUnit's test context
 	 * @param arguments   a list of test parameters
 	 * @param itemType    a type of the item
+	 * @param description a description of the item
+	 * @param startTime   a start time of the item
 	 */
 	protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull final List<Object> arguments,
 			@Nonnull final ItemType itemType, @Nullable final String description, @Nullable final Date startTime) {
 		idMapping.computeIfAbsent(context, c -> {
 			StartTestItemRQ rq = buildStartStepRq(c, arguments, itemType, description, startTime);
 			Launch launch = getLaunch(c);
-			Maybe<String> itemId = c.getParent()
-					.flatMap(parent -> Optional.ofNullable(idMapping.get(parent)))
-					.map(parentTest -> {
-						Maybe<String> item = launch.startTestItem(parentTest, rq);
-						if (getReporter().getParameters().isCallbackReportingEnabled()) {
-							TEST_ITEM_TREE.getTestItems()
-									.put(createItemTreeKey(rq.getName()), createTestItemLeaf(parentTest, item));
-						}
-						return item;
-					})
-					.orElseGet(() -> {
-						Maybe<String> item = launch.startTestItem(rq);
-						if (getReporter().getParameters().isCallbackReportingEnabled()) {
-							TEST_ITEM_TREE.getTestItems()
-									.put(createItemTreeKey(rq.getName()), createTestItemLeaf(item));
-						}
-						return item;
-					});
+
+			Maybe<String> parentId = c.getParent().flatMap(parent -> Optional.ofNullable(idMapping.get(parent))).orElse(null);
+			Maybe<String> itemId;
+			TestItemTree.TestItemLeaf leaf;
+			if (parentId == null) {
+				itemId = launch.startTestItem(rq);
+				leaf = createTestItemLeaf(itemId);
+			} else {
+				itemId = launch.startTestItem(parentId, rq);
+				leaf = createTestItemLeaf(parentId, itemId);
+			}
+			if (getReporter().getParameters().isCallbackReportingEnabled()) {
+				TEST_ITEM_TREE.getTestItems().put(createItemTreeKey(rq.getName()), leaf);
+			}
 			if (TEMPLATE == itemType) {
 				testTemplates.put(c, itemId);
 			}
@@ -515,12 +500,10 @@ protected void startTestItem(@Nonnull final ExtensionContext context, @Nonnull f
 	 * @param itemType      a method's item type (to display on RP)
 	 * @return an ID of the method
 	 */
-	protected Maybe<String> startBeforeAfter(Method method, ExtensionContext parentContext, ExtensionContext context,
-			ItemType itemType) {
+	protected Maybe<String> startBeforeAfter(Method method, ExtensionContext parentContext, ExtensionContext context, ItemType itemType) {
 		Launch launch = getLaunch(context);
 		StartTestItemRQ rq = buildStartConfigurationRq(method, parentContext, context, itemType);
-		return getItemId(parentContext).map(pid -> launch.startTestItem(pid, rq))
-				.orElseGet(() -> launch.startTestItem(rq));
+		return getItemId(parentContext).map(pid -> launch.startTestItem(pid, rq)).orElseGet(() -> launch.startTestItem(rq));
 	}
 
 	/**
@@ -576,8 +559,8 @@ protected void finishTestItem(@Nonnull final ExtensionContext context, @Nonnull
 		Maybe<String> id = idMapping.remove(context);
 		Maybe<OperationCompletionRS> finishResponse = launch.finishTestItem(id, rq);
 		if (getReporter().getParameters().isCallbackReportingEnabled()) {
-			ofNullable(TEST_ITEM_TREE.getTestItems()
-					.get(createItemTreeKey(context))).ifPresent(itemLeaf -> itemLeaf.setFinishResponse(finishResponse));
+			ofNullable(TEST_ITEM_TREE.getTestItems().get(createItemTreeKey(context))).ifPresent(itemLeaf -> itemLeaf.setFinishResponse(
+					finishResponse));
 		}
 	}
 
@@ -605,7 +588,7 @@ private static String getCodeRef(@Nonnull final Method method) {
 	}
 
 	private static String appendSuffixIfNotEmpty(final String str, @Nonnull final String suffix) {
-		return str + (suffix.isEmpty() ? "" : "$" + suffix);
+		return str + (StringUtils.isNotBlank(suffix) ? "$" + suffix : "");
 	}
 
 	@Nonnull
@@ -639,8 +622,7 @@ protected String getCodeRef(@Nonnull final ExtensionContext context) {
 	 * @return an {@link Optional} of a {@link Method}
 	 */
 	protected Optional<Method> getTestMethod(ExtensionContext context) {
-		return ofNullable(context.getTestMethod()
-				.orElseGet(() -> context.getParent().flatMap(this::getTestMethod).orElse(null)));
+		return ofNullable(context.getTestMethod().orElseGet(() -> context.getParent().flatMap(this::getTestMethod).orElse(null)));
 	}
 
 	/**
@@ -661,24 +643,75 @@ protected Optional<Method> getTestMethod(ExtensionContext context) {
 	 * @param arguments a list of parameter values
 	 * @return a list of parameters
 	 */
-	protected @Nonnull List<ParameterResource> getParameters(@Nonnull final Method method,
-			final List<Object> arguments) {
+	protected @Nonnull List<ParameterResource> getParameters(@Nonnull final Method method, final List<Object> arguments) {
 		return ParameterUtils.getParameters(method, arguments);
 	}
 
+	private Optional<Method> getOptionalTestMethod(ExtensionContext context) {
+		Optional<Method> optionalMethod = context.getTestMethod();
+		if (!optionalMethod.isPresent()) {
+			//if not present means that we are in the dynamic test, in this case we need to move to the parent context
+			Optional<ExtensionContext> parentContext = context.getParent();
+			if (!parentContext.isPresent()) {
+				return Optional.empty();
+			}
+			return parentContext.get().getTestMethod();
+		}
+		return optionalMethod;
+	}
+
+	private String getMethodName(String value) {
+		return value.length() > 1024 ? value.substring(0, 1021) + "..." : value;
+	}
+
+	/**
+	 * Extension point to customize test step name
+	 *
+	 * @param context  JUnit's test context
+	 * @param itemType a test method item type
+	 * @return Test/Step Name being sent to ReportPortal
+	 */
+	protected String createStepName(ExtensionContext context, ItemType itemType) {
+		String name = context.getDisplayName();
+		String defaultValue = getMethodName(name);
+
+		if (itemType != STEP) {
+			return defaultValue;
+		}
+
+		Optional<Method> optionalMethod = getOptionalTestMethod(context);
+		if (!optionalMethod.isPresent()) {
+			return defaultValue;
+		}
+		Method method = optionalMethod.get();
+
+		com.epam.reportportal.annotations.DisplayName displayNameFromMethod = method.getAnnotation(com.epam.reportportal.annotations.DisplayName.class);
+		if (displayNameFromMethod != null) {
+			return getMethodName(displayNameFromMethod.value());
+		}
+
+		com.epam.reportportal.annotations.DisplayName displayNameFromClass = method.getDeclaringClass()
+				.getAnnotation(com.epam.reportportal.annotations.DisplayName.class);
+		if (displayNameFromClass != null) {
+			return getMethodName(displayNameFromClass.value());
+		}
+
+		return defaultValue;
+	}
+
 	/**
 	 * Extension point to customize test step creation event/request
 	 *
 	 * @param context     JUnit's test context
 	 * @param arguments   a test arguments list
 	 * @param itemType    a test method item type
+	 * @param description a description of the item
 	 * @param startTime   a start time of the test
 	 * @return Request to ReportPortal
 	 */
 	@Nonnull
-	protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext context,
-			@Nonnull final List<Object> arguments, @Nonnull final ItemType itemType, @Nullable final String description,
-			@Nullable final Date startTime) {
+	protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext context, @Nonnull final List<Object> arguments,
+			@Nonnull final ItemType itemType, @Nullable final String description, @Nullable final Date startTime) {
 		StartTestItemRQ rq = new StartTestItemRQ();
 		rq.setStartTime(ofNullable(startTime).orElseGet(Calendar.getInstance()::getTime));
 		rq.setName(createStepName(context, itemType));
@@ -686,10 +719,7 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext conte
 		rq.setType(itemType == TEMPLATE ? SUITE.name() : itemType.name());
 		String codeRef = getCodeRef(context);
 		rq.setCodeRef(codeRef);
-		rq.setAttributes(context.getTags()
-				.stream()
-				.map(it -> new ItemAttributesRQ(null, it))
-				.collect(Collectors.toSet()));
+		rq.setAttributes(context.getTags().stream().map(it -> new ItemAttributesRQ(null, it)).collect(Collectors.toSet()));
 		if (SUITE == itemType) {
 			context.getTestClass().ifPresent(c -> rq.getAttributes().addAll(getAttributes(c)));
 		}
@@ -700,6 +730,9 @@ protected StartTestItemRQ buildStartStepRq(@Nonnull final ExtensionContext conte
 			rq.setParameters(getParameters(m, arguments));
 			return getTestCaseId(m, codeRef, arguments, context.getTestInstance().orElse(null));
 		}).orElseGet(() -> TestCaseIdUtils.getTestCaseId(codeRef, arguments));
+		if (STEP == itemType) {
+			testParameters.put(context, rq.getParameters());
+		}
 		rq.setTestCaseId(ofNullable(caseId).map(TestCaseIdEntry::getId).orElse(null));
 		return rq;
 	}
@@ -758,23 +791,36 @@ protected void createSkippedSteps(ExtensionContext context, Throwable cause) {
 	 * @param status  a test item execution result
 	 * @return Request to ReportPortal
 	 */
-	@SuppressWarnings("unused")
 	@Nonnull
 	protected FinishTestItemRQ buildFinishTestRq(@Nonnull ExtensionContext context, @Nullable ItemStatus status) {
 		FinishTestItemRQ rq = new FinishTestItemRQ();
-		if (status != ItemStatus.PASSED && testThrowable.containsKey(context)) {
-			ItemType itemType = STEP;
-			String description = String.format(DESCRIPTION_TEST_ERROR_FORMAT,
-					createStepDescription(context, itemType),
-					ExceptionUtils.getStackTrace(testThrowable.get(context)));
+		ItemStatus myStatus = ofNullable(status).orElseGet(() -> getExecutionStatus(context));
+		Optional<Throwable> myException = context.getExecutionException();
+		if (myStatus != ItemStatus.PASSED && myException.isPresent()) {
+			String stepDescription = createStepDescription(context, STEP);
+			String stackTrace = String.format(DESCRIPTION_TEST_ERROR_FORMAT, getStackTrace(myException.get(), new Throwable()));
+			String description = StringUtils.isNotBlank(stepDescription) ?
+					MarkdownUtils.asTwoParts(stepDescription, stackTrace) :
+					stackTrace;
 			rq.setDescription(description);
 		}
+		rq.setIssue(getIssue(context));
 		ofNullable(status).ifPresent(s -> rq.setStatus(s.name()));
 		rq.setEndTime(Calendar.getInstance().getTime());
-		testThrowable.remove(context);
 		return rq;
 	}
 
+	@Nullable
+	protected com.epam.ta.reportportal.ws.model.issue.Issue getIssue(@Nonnull ExtensionContext context) {
+		String stepName = createStepName(context, STEP);
+		List<ParameterResource> parameters = testParameters.containsKey(context) ? testParameters.remove(context) : Collections.emptyList();
+		return getOptionalTestMethod(context).map(m -> ofNullable(m.getAnnotation(Issues.class)).map(i -> IssueUtils.createIssue(i,
+						stepName,
+						parameters
+				)).orElseGet(() -> IssueUtils.createIssue(m.getAnnotation(Issue.class), stepName, parameters)))
+				.orElse(null);
+	}
+
 	/**
 	 * Extension point to customize a test item result on it's finish
 	 *
@@ -791,44 +837,6 @@ protected FinishTestItemRQ buildFinishTestItemRq(@Nonnull ExtensionContext conte
 		return rq;
 	}
 
-	/**
-	 * Extension point to customize test step name
-	 *
-	 * @param context JUnit's test context
-	 * @param itemType a test method item type
-	 * @return Test/Step Name being sent to ReportPortal
-	 */
-	protected String createStepName(ExtensionContext context, ItemType itemType) {
-		String name = context.getDisplayName();
-		String defaultValue = getMethodName(name);
-
-		if (itemType != STEP) {
-			return defaultValue;
-		}
-
-		Optional<Method> optionalMethod = getOptionalTestMethod(context);
-		if (!optionalMethod.isPresent()) {
-			return defaultValue;
-		}
-		Method method = optionalMethod.get();
-
-		com.epam.reportportal.annotations.DisplayName displayNameFromMethod = method.getAnnotation(com.epam.reportportal.annotations.DisplayName.class);
-		if (displayNameFromMethod != null) {
-			return getMethodName(displayNameFromMethod.value());
-		}
-
-		com.epam.reportportal.annotations.DisplayName displayNameFromClass = method.getDeclaringClass().getAnnotation(com.epam.reportportal.annotations.DisplayName.class);
-		if (displayNameFromClass != null) {
-			return getMethodName(displayNameFromClass.value());
-		}
-
-		return defaultValue;
-	}
-
-	private String getMethodName(String value) {
-		return value.length() > 1024 ? value.substring(0, 1021) + "..." : value;
-	}
-
 	/**
 	 * Extension point to customize beforeXXX step name
 	 *
@@ -861,7 +869,8 @@ protected String createConfigurationName(@Nonnull Class<?> testClass, @Nonnull M
 	/**
 	 * Extension point to customize test step description
 	 *
-	 * @param context JUnit's test context
+	 * @param context  JUnit's test context
+	 * @param itemType a test method item type
 	 * @return Test/Step Description being sent to ReportPortal
 	 */
 	@Nonnull
@@ -871,37 +880,24 @@ protected String createStepDescription(ExtensionContext context, final ItemType
 			return defaultValue;
 		}
 		Optional<Method> optionalMethod = getOptionalTestMethod(context);
-		if (!optionalMethod.isPresent()){
+		if (!optionalMethod.isPresent()) {
 			return defaultValue;
 		}
 		Method method = optionalMethod.get();
 
 		Description descriptionFromMethod = method.getAnnotation(Description.class);
-		if(descriptionFromMethod != null){
+		if (descriptionFromMethod != null) {
 			return descriptionFromMethod.value();
 		}
 
 		Description descriptionFromClass = method.getDeclaringClass().getAnnotation(Description.class);
-		if(descriptionFromClass != null){
+		if (descriptionFromClass != null) {
 			return descriptionFromClass.value();
 		}
 
 		return defaultValue;
 	}
 
-	private Optional<Method> getOptionalTestMethod(ExtensionContext context){
-		Optional<Method> optionalMethod = context.getTestMethod();
-		if(!optionalMethod.isPresent()){
-			//if not present means that we are in the dynamic test, in this case we need to move to the parent context
-			Optional<ExtensionContext> parentContext = context.getParent();
-			if(!parentContext.isPresent()){
-				return Optional.empty();
-			}
-			return parentContext.get().getTestMethod();
-		}
-		return optionalMethod;
-	}
-
 	/**
 	 * Extension point to customize beforeXXX step description
 	 *
@@ -922,8 +918,8 @@ protected String createConfigurationDescription(Class<?> testClass, Method metho
 	 * @param throwable         An exception which caused the skip
 	 * @param eventTime         <code>@BeforeEach</code> start time
 	 */
-	protected void reportSkippedStep(ReflectiveInvocationContext<Method> invocationContext, ExtensionContext context,
-			Throwable throwable, Date eventTime) {
+	protected void reportSkippedStep(ReflectiveInvocationContext<Method> invocationContext, ExtensionContext context, Throwable throwable,
+			Date eventTime) {
 		Date skipStartTime = Calendar.getInstance().getTime();
 		if (skipStartTime.after(eventTime)) {
 			// to fix item ordering when @AfterEach starts in the same millisecond as skipped test
@@ -945,8 +941,8 @@ protected void reportSkippedStep(ReflectiveInvocationContext<Method> invocationC
 	 * @param eventTime         <code>@BeforeAll</code> start time
 	 */
 	@SuppressWarnings("unused")
-	protected void reportSkippedClassTests(ReflectiveInvocationContext<Method> invocationContext,
-			ExtensionContext context, Date eventTime) {
+	protected void reportSkippedClassTests(ReflectiveInvocationContext<Method> invocationContext, ExtensionContext context,
+			Date eventTime) {
 	}
 
 	/**
@@ -961,7 +957,7 @@ protected void sendStackTraceToRP(final Throwable cause) {
 			rq.setLevel("ERROR");
 			rq.setLogTime(Calendar.getInstance().getTime());
 			if (cause != null) {
-				rq.setMessage(getStackTrace(cause));
+				rq.setMessage(getStackTrace(cause, new Throwable()));
 			} else {
 				rq.setMessage("Test has failed without exception");
 			}
diff --git a/src/test/java/com/epam/reportportal/junit5/BasicTest.java b/src/test/java/com/epam/reportportal/junit5/BasicTest.java
index b201217..a803465 100644
--- a/src/test/java/com/epam/reportportal/junit5/BasicTest.java
+++ b/src/test/java/com/epam/reportportal/junit5/BasicTest.java
@@ -16,7 +16,7 @@
 
 package com.epam.reportportal.junit5;
 
-import com.epam.reportportal.junit5.features.basic.TestFailure;
+import com.epam.reportportal.junit5.features.TestFailure;
 import com.epam.reportportal.junit5.util.TestUtils;
 import com.epam.reportportal.listeners.ItemStatus;
 import com.epam.reportportal.service.Launch;
diff --git a/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java
index 734eb42..1f3fb19 100644
--- a/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java
+++ b/src/test/java/com/epam/reportportal/junit5/ErrorLastLogTest.java
@@ -8,6 +8,7 @@
 import com.epam.reportportal.service.Launch;
 import com.epam.reportportal.service.ReportPortal;
 import com.epam.reportportal.service.ReportPortalClient;
+import com.epam.reportportal.utils.formatting.MarkdownUtils;
 import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
@@ -30,122 +31,132 @@
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public class ErrorLastLogTest {
 
-    private final String testErrorMessagePattern = "%s\nError: \n%s";
-    private final String assertErrorMessage = "org.opentest4j.AssertionFailedError: expected: <0> but was: <1>";
-    private final String exceptionStepErrorMessage = "java.util.NoSuchElementException: Error message";
-    private final String testExceptionMessage = "java.lang.RuntimeException: Critical error";
-    private final String assertDescriptionMessage = "0 and 1 is not equal";
-    private final String stepDescriptionMessage = "Login issue";
-    private final String failedStatus = "FAILED";
-    private final String passedStatus = "PASSED";
-    static final String testClassUuid = namedId("class");
-    static final String testMethodUuid = namedId("test");
-    public static class ErrorDescriptionTestExtension extends ReportPortalExtension {
+	private static final String TEST_ERROR_MESSAGE_PATTERN = "Error: \n%s";
+	private static final String ASSERT_ERROR_MESSAGE = "org.opentest4j.AssertionFailedError: expected: <0> but was: <1>";
+	private static final String EXCEPTION_STEP_ERROR_MESSAGE = "java.util.NoSuchElementException: Error message";
+	private static final String TEST_EXCEPTION_MESSAGE = "java.lang.RuntimeException: Critical error";
+	private static final String ASSERT_DESCRIPTION_MESSAGE = "0 and 1 is not equal";
+	private static final String STEP_DESCRIPTION_MESSAGE = "Login issue";
+	private static final String FAILED_STATUS = "FAILED";
+	private static final String PASSED_STATUS = "PASSED";
+	private static final String TEST_CLASS_UUID = namedId("class");
+	private static final String TEST_METHOD_UUID = namedId("test");
 
-        static final ThreadLocal<ReportPortalClient> client = new ThreadLocal<>();
-        static final ThreadLocal<Launch> launch = new ThreadLocal<>();
-        public static void init() {
-            client.set(mock(ReportPortalClient.class));
-            TestUtils.mockLaunch(client.get(), "launchUuid", testClassUuid, testMethodUuid);
-            TestUtils.mockLogging(client.get());
-            ReportPortal reportPortal = ReportPortal.create(client.get(), TestUtils.standardParameters());
-            launch.set(reportPortal.newLaunch(TestUtils.launchRQ(reportPortal.getParameters())));
+	public static class ErrorDescriptionTestExtension extends ReportPortalExtension {
 
-        }
+		static final ThreadLocal<ReportPortalClient> client = new ThreadLocal<>();
+		static final ThreadLocal<Launch> launch = new ThreadLocal<>();
 
-        @Override
-        protected Launch getLaunch(ExtensionContext context) {
-            return launch.get();
-        }
+		public static void init() {
+			client.set(mock(ReportPortalClient.class));
+			TestUtils.mockLaunch(client.get(), "launchUuid", TEST_CLASS_UUID, TEST_METHOD_UUID);
+			TestUtils.mockLogging(client.get());
+			ReportPortal reportPortal = ReportPortal.create(client.get(), TestUtils.standardParameters());
+			launch.set(reportPortal.newLaunch(TestUtils.launchRQ(reportPortal.getParameters())));
 
-    }
+		}
 
-    public static class Listener implements TestExecutionListener {
-        public Deque<TestExecutionResult> results = new ConcurrentLinkedDeque<>();
+		@Override
+		protected Launch getLaunch(ExtensionContext context) {
+			return launch.get();
+		}
 
-        @Override
-        public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
-            if (testIdentifier.isTest()) {
-                results.add(testExecutionResult);
-            }
-        }
-    }
+	}
 
-    @Test
-    public void verify_last_error_log_exception() {
-        ErrorDescriptionTestExtension.init();
-        Listener listener = new Listener();
-        TestUtils.runClasses(listener, ErrorLastLogFeatureWithExceptionTest.class);
+	public static class Listener implements TestExecutionListener {
+		public Deque<TestExecutionResult> results = new ConcurrentLinkedDeque<>();
 
-        ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
+		@Override
+		public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
+			if (testIdentifier.isTest()) {
+				results.add(testExecutionResult);
+			}
+		}
+	}
 
-        ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
-        verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture());
+	@Test
+	public void verify_last_error_log_exception() {
+		ErrorDescriptionTestExtension.init();
+		Listener listener = new Listener();
+		TestUtils.runClasses(listener, ErrorLastLogFeatureWithExceptionTest.class);
 
+		ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
 
-        List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
+		ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture());
 
-        FinishTestItemRQ testCaseWithException = finishTests.get(0);
+		List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
 
-        assertThat(testCaseWithException.getDescription(), startsWith(String.format(testErrorMessagePattern, "", testExceptionMessage)));
-        assertThat(testCaseWithException.getStatus(), equalTo(failedStatus));
+		FinishTestItemRQ testCaseWithException = finishTests.get(0);
 
-    }
+		assertThat(testCaseWithException.getDescription(), startsWith(String.format(TEST_ERROR_MESSAGE_PATTERN, TEST_EXCEPTION_MESSAGE)));
+		assertThat(testCaseWithException.getStatus(), equalTo(FAILED_STATUS));
 
-    @Test
-    public void verify_last_error_log_step() {
-        ErrorDescriptionTestExtension.init();
-        Listener listener = new Listener();
-        TestUtils.runClasses(listener, ErrorLastLogFeatureWithStepTest.class);
+	}
 
-        ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
+	@Test
+	public void verify_last_error_log_step() {
+		ErrorDescriptionTestExtension.init();
+		Listener listener = new Listener();
+		TestUtils.runClasses(listener, ErrorLastLogFeatureWithStepTest.class);
 
-        ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
-        verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture());
+		ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
 
-        List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
+		ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture());
 
-        FinishTestItemRQ testCaseWithDescriptionAndStepError = finishTests.get(0);
+		List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
 
-        assertThat(testCaseWithDescriptionAndStepError.getDescription(), startsWith(String.format(testErrorMessagePattern, stepDescriptionMessage, exceptionStepErrorMessage)));
-        assertThat(testCaseWithDescriptionAndStepError.getStatus(), equalTo(failedStatus));
-    }
+		FinishTestItemRQ testCaseWithDescriptionAndStepError = finishTests.get(0);
 
-    @Test
-    public void verify_last_error_log_assertion_error() {
-        ErrorDescriptionTestExtension.init();
-        Listener listener = new Listener();
-        TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionErrorTest.class);
+		assertThat(testCaseWithDescriptionAndStepError.getDescription(),
+				startsWith(MarkdownUtils.asTwoParts(STEP_DESCRIPTION_MESSAGE,
+						String.format(TEST_ERROR_MESSAGE_PATTERN, EXCEPTION_STEP_ERROR_MESSAGE)
+				))
+		);
+		assertThat(testCaseWithDescriptionAndStepError.getStatus(), equalTo(FAILED_STATUS));
+	}
 
-        ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
+	@Test
+	public void verify_last_error_log_assertion_error() {
+		ErrorDescriptionTestExtension.init();
+		Listener listener = new Listener();
+		TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionErrorTest.class);
 
-        ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
-        verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture());
+		ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
 
-        List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
+		ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture());
 
-        FinishTestItemRQ testCaseAssertException = finishTests.get(0);
+		List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
 
-        assertThat(testCaseAssertException.getDescription(), startsWith(String.format(testErrorMessagePattern, assertDescriptionMessage, assertErrorMessage)));
-        assertThat(testCaseAssertException.getStatus(), equalTo(failedStatus));
-    }
+		FinishTestItemRQ testCaseAssertException = finishTests.get(0);
 
-    @Test
-    public void verify_last_error_log_assertion_passed() {
-        ErrorDescriptionTestExtension.init();
-        Listener listener = new Listener();
-        TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionPassedTest.class);
+		assertThat(testCaseAssertException.getDescription(),
+				startsWith(MarkdownUtils.asTwoParts(
+						ASSERT_DESCRIPTION_MESSAGE,
+						String.format(TEST_ERROR_MESSAGE_PATTERN, ASSERT_ERROR_MESSAGE)
+				))
+		);
+		assertThat(testCaseAssertException.getStatus(), equalTo(FAILED_STATUS));
+	}
 
-        ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
+	@Test
+	public void verify_last_error_log_assertion_passed() {
+		ErrorDescriptionTestExtension.init();
+		Listener listener = new Listener();
+		TestUtils.runClasses(listener, ErrorLastLogFeatureWithAssertionPassedTest.class);
 
-        ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
-        verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(testMethodUuid), finishTestCaptor.capture());
+		ReportPortalClient client = ErrorDescriptionTestExtension.client.get();
 
-        List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
+		ArgumentCaptor<FinishTestItemRQ> finishTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(client, timeout(1000).atLeastOnce()).finishTestItem(same(TEST_METHOD_UUID), finishTestCaptor.capture());
 
-        FinishTestItemRQ testCaseWithDescriptionAndPassed = finishTests.get(0);
+		List<FinishTestItemRQ> finishTests = finishTestCaptor.getAllValues();
 
-        assertThat(testCaseWithDescriptionAndPassed.getStatus(), equalTo(passedStatus));
+		FinishTestItemRQ testCaseWithDescriptionAndPassed = finishTests.get(0);
 
-    }
+		assertThat(testCaseWithDescriptionAndPassed.getStatus(), equalTo(PASSED_STATUS));
+
+	}
 }
diff --git a/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java
new file mode 100644
index 0000000..7547417
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/IssueReportingTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5;
+
+import com.epam.reportportal.junit5.features.issue.*;
+import com.epam.reportportal.junit5.util.TestUtils;
+import com.epam.reportportal.listeners.ItemStatus;
+import com.epam.reportportal.service.Launch;
+import com.epam.reportportal.util.test.CommonUtils;
+import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
+import com.epam.ta.reportportal.ws.model.OperationCompletionRS;
+import com.epam.ta.reportportal.ws.model.issue.Issue;
+import io.reactivex.Maybe;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.mockito.ArgumentCaptor;
+import org.mockito.stubbing.Answer;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@TestInstance(TestInstance.Lifecycle.PER_METHOD)
+public class IssueReportingTest {
+	public static class TestExtension extends ReportPortalExtension {
+		static Launch LAUNCH;
+
+		@Override
+		protected Launch getLaunch(ExtensionContext context) {
+			return LAUNCH;
+		}
+	}
+
+	private final String suiteId = CommonUtils.namedId("suite_");
+	private final Maybe<String> suiteMaybe = Maybe.just(suiteId);
+	private final String stepOneId = CommonUtils.namedId("step_");
+	private final Maybe<String> stepOneMaybe = Maybe.just(stepOneId);
+	private final String stepTwoId = CommonUtils.namedId("step_");
+	private final Maybe<String> stepTwoMaybe = Maybe.just(stepTwoId);
+	private final String stepThreeId = CommonUtils.namedId("step_");
+	private final Maybe<String> stepThreeMaybe = Maybe.just(stepThreeId);
+	private final Queue<Maybe<String>> stepIds = new LinkedList<>(Arrays.asList(stepOneMaybe, stepTwoMaybe, stepThreeMaybe));
+
+	@BeforeAll
+	public static void setupProperty() {
+		System.setProperty("reportDisabledTests", Boolean.TRUE.toString());
+	}
+
+	@BeforeEach
+	public void setupMock() {
+		Launch launch = mock(Launch.class);
+		IssueReportingTest.TestExtension.LAUNCH = launch;
+		when(launch.startTestItem(any())).thenAnswer((Answer<Maybe<String>>) invocation -> suiteMaybe);
+		when(launch.startTestItem(any(), any())).thenAnswer((Answer<Maybe<String>>) invocation -> CommonUtils.createMaybeUuid());
+		when(launch.startTestItem(same(suiteMaybe), any())).thenAnswer((Answer<Maybe<String>>) invocation -> stepIds.poll());
+		when(launch.startTestItem(same(stepOneMaybe), any())).thenAnswer((Answer<Maybe<String>>) invocation -> stepIds.poll());
+		when(launch.finishTestItem(any(),
+				any()
+		)).thenAnswer((Answer<Maybe<OperationCompletionRS>>) invocation -> Maybe.just(new OperationCompletionRS("OK")));
+	}
+
+	@Test
+	public void verify_simple_test_failure() {
+		TestUtils.runClasses(SimpleIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = testCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("pb001"));
+		assertThat(issue.getComment(), equalTo(SimpleIssueTest.FAILURE_MESSAGE));
+	}
+
+	@Test
+	public void verify_test_failure_with_two_issues() {
+		TestUtils.runClasses(SimpleTwoIssuesTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = testCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(SimpleTwoIssuesTest.FAILURE_MESSAGE));
+	}
+
+	@Test
+	public void verify_parameterized_test_failure_with_one_issue() {
+		TestUtils.runClasses(ParameterizedWithOneIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture());
+		ArgumentCaptor<FinishTestItemRQ> secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), nullValue());
+
+		finishTestItemRQ = secondTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(ParameterizedWithOneIssueTest.ISSUE_MESSAGE));
+	}
+
+	@Test
+	public void verify_parameterized_test_failure_with_two_issues() {
+		TestUtils.runClasses(ParameterizedWithTwoIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture());
+		ArgumentCaptor<FinishTestItemRQ> secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(ParameterizedWithTwoIssueTest.ISSUE_MESSAGE));
+
+		finishTestItemRQ = secondTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("pb001"));
+		assertThat(issue.getComment(), equalTo(ParameterizedWithTwoIssueTest.ISSUE_MESSAGE));
+	}
+
+	@Test
+	public void verify_dynamic_test_failure() {
+		TestUtils.runClasses(DynamicIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepTwoMaybe), testCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = testCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(DynamicIssueTest.FAILURE_MESSAGE));
+	}
+
+	@Test
+	public void verify_two_dynamic_test_failures() {
+		TestUtils.runClasses(TwoDynamicIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture());
+		ArgumentCaptor<FinishTestItemRQ> secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(TwoDynamicIssueTest.FAILURE_MESSAGE));
+
+		finishTestItemRQ = secondTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(TwoDynamicIssueTest.FAILURE_MESSAGE));
+	}
+
+	@Test
+	public void verify_two_dynamic_test_failures_two_issues() {
+		TestUtils.runClasses(TwoDynamicTwoIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> firstTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepTwoMaybe), firstTestCaptor.capture());
+		ArgumentCaptor<FinishTestItemRQ> secondTestCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepThreeMaybe), secondTestCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = firstTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("ab001"));
+		assertThat(issue.getComment(), equalTo(TwoDynamicTwoIssueTest.FAILURE_MESSAGE));
+
+		finishTestItemRQ = secondTestCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.FAILED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("pb001"));
+		assertThat(issue.getComment(), equalTo(TwoDynamicTwoIssueTest.FAILURE_MESSAGE));
+	}
+
+	@Test
+	public void verify_simple_test_skip() {
+		TestUtils.runClasses(SimpleSkippedIssueTest.class);
+
+		Launch launch = IssueReportingTest.TestExtension.LAUNCH;
+		ArgumentCaptor<FinishTestItemRQ> testCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
+		verify(launch).finishTestItem(same(stepOneMaybe), testCaptor.capture());
+
+		FinishTestItemRQ finishTestItemRQ = testCaptor.getValue();
+		assertThat(finishTestItemRQ.getStatus(), equalTo(ItemStatus.SKIPPED.name()));
+		assertThat(finishTestItemRQ.getIssue(), notNullValue());
+		Issue issue = finishTestItemRQ.getIssue();
+		assertThat(issue.getIssueType(), equalTo("pb001"));
+		assertThat(issue.getComment(), equalTo(SimpleSkippedIssueTest.FAILURE_MESSAGE));
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java b/src/test/java/com/epam/reportportal/junit5/features/TestFailure.java
similarity index 87%
rename from src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java
rename to src/test/java/com/epam/reportportal/junit5/features/TestFailure.java
index 159ba85..31159aa 100644
--- a/src/test/java/com/epam/reportportal/junit5/features/basic/TestFailure.java
+++ b/src/test/java/com/epam/reportportal/junit5/features/TestFailure.java
@@ -1,11 +1,11 @@
 /*
- * Copyright 2022 EPAM Systems
+ * Copyright 2024 EPAM Systems
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *     https://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.epam.reportportal.junit5.features.basic;
+package com.epam.reportportal.junit5.features;
 
 import com.epam.reportportal.junit5.BasicTest;
 import org.junit.jupiter.api.Assertions;
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java
new file mode 100644
index 0000000..875cc43
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/DynamicIssueTest.java
@@ -0,0 +1,24 @@
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.TestFactory;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class DynamicIssueTest {
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@TestFactory
+	@Issue(value = "ab001", comment = FAILURE_MESSAGE)
+	Stream<DynamicTest> testForTestFactory() {
+		return Stream.of(dynamicTest("My dynamic test", () -> {
+			throw new IllegalStateException(FAILURE_MESSAGE);
+		}));
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java
new file mode 100644
index 0000000..1010f5c
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithOneIssueTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.annotations.TestFilter;
+import com.epam.reportportal.annotations.TestParamFilter;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class ParameterizedWithOneIssueTest {
+
+	public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: ";
+	public static final String ISSUE_MESSAGE = "This test is expected to fail";
+
+	@ParameterizedTest
+	@ValueSource(booleans = { true, false })
+	@Issue(value = "ab001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "false") }))
+	public void failureTest(boolean param) {
+		throw new IllegalStateException(FAILURE_MESSAGE + param);
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java
new file mode 100644
index 0000000..4d156c4
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/ParameterizedWithTwoIssueTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.annotations.TestFilter;
+import com.epam.reportportal.annotations.TestParamFilter;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class ParameterizedWithTwoIssueTest {
+
+	public static final String FAILURE_MESSAGE = "This parameterized test is expected to fail: ";
+	public static final String ISSUE_MESSAGE = "This test is expected to fail";
+
+	@ParameterizedTest
+	@ValueSource(booleans = { true, false })
+	@Issue(value = "ab001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "true") }))
+	@Issue(value = "pb001", comment = ISSUE_MESSAGE, filter = @TestFilter(param = { @TestParamFilter(valueStartsWith = "false") }))
+	public void failureTest(boolean param) {
+		throw new IllegalStateException(FAILURE_MESSAGE + param);
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java
new file mode 100644
index 0000000..6b754be
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleIssueTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class SimpleIssueTest {
+
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@Test
+	@Issue(value = "pb001", comment = FAILURE_MESSAGE)
+	public void failureTest() {
+		throw new IllegalStateException(FAILURE_MESSAGE);
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java
new file mode 100644
index 0000000..c82655d
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleSkippedIssueTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class SimpleSkippedIssueTest {
+
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@Test
+	@Issue(value = "pb001", comment = FAILURE_MESSAGE)
+	@Disabled
+	public void failureTest() {
+		throw new IllegalStateException(FAILURE_MESSAGE);
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java
new file mode 100644
index 0000000..562e2f8
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/SimpleTwoIssuesTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class SimpleTwoIssuesTest {
+
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@Test
+	@Issue(value = "ab001", comment = FAILURE_MESSAGE)
+	@Issue(value = "pb001", comment = FAILURE_MESSAGE)
+	public void failureTest() {
+		throw new IllegalStateException(FAILURE_MESSAGE);
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java
new file mode 100644
index 0000000..cda7051
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicIssueTest.java
@@ -0,0 +1,26 @@
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.TestFactory;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class TwoDynamicIssueTest {
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@TestFactory
+	@Issue(value = "ab001", comment = FAILURE_MESSAGE)
+	Stream<DynamicTest> testForTestFactory() {
+		return Stream.of(dynamicTest("My dynamic test", () -> {
+			throw new IllegalStateException(FAILURE_MESSAGE);
+		}), dynamicTest("My dynamic test 2", () -> {
+			throw new IllegalStateException(FAILURE_MESSAGE);
+		}));
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java
new file mode 100644
index 0000000..442c6db
--- /dev/null
+++ b/src/test/java/com/epam/reportportal/junit5/features/issue/TwoDynamicTwoIssueTest.java
@@ -0,0 +1,29 @@
+package com.epam.reportportal.junit5.features.issue;
+
+import com.epam.reportportal.annotations.Issue;
+import com.epam.reportportal.annotations.TestFilter;
+import com.epam.reportportal.annotations.TestNameFilter;
+import com.epam.reportportal.junit5.IssueReportingTest;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.TestFactory;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.DynamicTest.dynamicTest;
+
+@ExtendWith(IssueReportingTest.TestExtension.class)
+public class TwoDynamicTwoIssueTest {
+	public static final String FAILURE_MESSAGE = "This test is expected to fail";
+
+	@TestFactory
+	@Issue(value = "ab001", comment = FAILURE_MESSAGE, filter = { @TestFilter(name = @TestNameFilter(endsWith = "test")) })
+	@Issue(value = "pb001", comment = FAILURE_MESSAGE, filter = { @TestFilter(name = @TestNameFilter(contains = "test 2")) })
+	Stream<DynamicTest> testForTestFactory() {
+		return Stream.of(dynamicTest("My dynamic test", () -> {
+			throw new IllegalStateException(FAILURE_MESSAGE);
+		}), dynamicTest("My dynamic test 2", () -> {
+			throw new IllegalStateException(FAILURE_MESSAGE);
+		}));
+	}
+}
diff --git a/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java b/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java
index 2539127..aaf2291 100644
--- a/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java
+++ b/src/test/java/com/epam/reportportal/junit5/features/step/ManualStepReporterFeatureTest.java
@@ -40,19 +40,22 @@ public class ManualStepReporterFeatureTest {
 	private static final Logger LOGGER = LoggerFactory.getLogger(ManualStepReporterFeatureTest.class);
 
 	@Test
-	public void manualStepTest() {
+	public void manualStepTest() throws InterruptedException {
 
 		StepReporter stepReporter = Launch.currentLaunch().getStepReporter();
 		stepReporter.sendStep(FIRST_NAME);
 		LOGGER.info("First info log of the first step");
 		LOGGER.info("Second info log of the first step");
+		Thread.sleep(100);
 
 		stepReporter.sendStep(SECOND_NAME);
 		LOGGER.error("First error log of the second step");
 
+		Thread.sleep(100);
 		stepReporter.sendStep(ItemStatus.FAILED, THIRD_NAME, new File("pug/unlucky.jpg"));
 		LOGGER.error("Second error log of the second step");
 
+		Thread.sleep(100);
 		stepReporter.finishPreviousStep();
 
 		LOGGER.error("Main test method error log");