Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Release #45

Merged
merged 3 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## [Unreleased]
### Changed
- Client version updated on [5.2.1](https://github.com/reportportal/client-java/releases/tag/5.2.1), by @HardNorth

## [5.1.5]
### Changed
Expand Down
108 changes: 52 additions & 56 deletions README.md

Large diffs are not rendered by default.

108 changes: 52 additions & 56 deletions README_TEMPLATE.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ repositories {
}

dependencies {
api 'com.epam.reportportal:client-java:5.1.22'
api 'com.epam.reportportal:client-java:5.2.1'
api 'com.epam.reportportal:commons-model:5.0.0'
api 'com.google.code.findbugs:jsr305:3.0.2'
api "io.cucumber:cucumber-java:${project.cucumber_version}"

implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'org.slf4j:slf4j-api:2.0.7'

testImplementation 'com.epam.reportportal:agent-java-test-utils:0.0.2'
Expand All @@ -51,8 +52,8 @@ dependencies {
testImplementation 'org.hamcrest:hamcrest-core:2.2'
testImplementation 'org.mockito:mockito-core:3.3.3'
testImplementation 'org.mockito:mockito-junit-jupiter:3.3.3'
testImplementation 'ch.qos.logback:logback-classic:1.3.8'
testImplementation 'com.epam.reportportal:logger-java-logback:5.1.5'
testImplementation 'ch.qos.logback:logback-classic:1.3.12'
testImplementation 'com.epam.reportportal:logger-java-logback:5.2.0'
testImplementation ("org.junit.platform:junit-platform-runner:${project.junit_runner_version}") {
exclude module: 'junit'
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version=5.1.6-SNAPSHOT
version=5.2.0-SNAPSHOT
description=EPAM Report portal. Cucumber version 2 integration
cucumber_version=2.4.0
junit_version=5.6.3
Expand Down
39 changes: 18 additions & 21 deletions src/main/java/com/epam/reportportal/cucumber/AbstractReporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,29 @@
import com.epam.reportportal.annotations.TestCaseId;
import com.epam.reportportal.annotations.attribute.Attributes;
import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.listeners.ItemType;
import com.epam.reportportal.listeners.ListenerParameters;
import com.epam.reportportal.message.ReportPortalMessage;
import com.epam.reportportal.service.Launch;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.item.TestCaseIdEntry;
import com.epam.reportportal.service.tree.TestItemTree;
import com.epam.reportportal.utils.*;
import com.epam.reportportal.utils.files.ByteSource;
import com.epam.reportportal.utils.markdown.MarkdownUtils;
import com.epam.reportportal.utils.properties.SystemAttributesExtractor;
import com.epam.ta.reportportal.ws.model.FinishExecutionRQ;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
import com.epam.ta.reportportal.ws.model.ParameterResource;
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
import com.epam.ta.reportportal.ws.model.attribute.ItemAttributesRQ;
import com.epam.ta.reportportal.ws.model.launch.StartLaunchRQ;
import com.google.common.io.ByteSource;
import cucumber.api.HookType;
import cucumber.api.Result;
import cucumber.api.TestCase;
import cucumber.api.TestStep;
import cucumber.api.event.*;
import cucumber.api.formatter.Formatter;
import cucumber.runtime.StepDefinitionMatch;
import gherkin.ast.Feature;
import gherkin.ast.Step;
import gherkin.ast.Tag;
Expand Down Expand Up @@ -705,6 +706,7 @@ protected void finishFeature(Maybe<String> itemId, Date dateTime) {
LOGGER.error("BUG: Trying to finish unspecified test item.");
return;
}
//noinspection ReactiveStreamsUnusedPublisher
launch.get().finishTestItem(itemId, buildFinishTestItemRequest(itemId, dateTime, null));
}

Expand Down Expand Up @@ -744,6 +746,7 @@ protected Date finishTestItem(@Nullable Maybe<String> itemId, @Nullable Result.T
}

FinishTestItemRQ rq = buildFinishTestItemRequest(itemId, null, mapItemStatus(status));
//noinspection ReactiveStreamsUnusedPublisher
launch.get().finishTestItem(itemId, rq);
return rq.getEndTime();
}
Expand Down Expand Up @@ -796,7 +799,7 @@ protected String buildMultilineArgument(@Nonnull TestStep step) {

StringBuilder marg = new StringBuilder();
if (table != null) {
marg.append(formatDataTable(table));
marg.append(MarkdownUtils.formatDataTable(table));
}

if (docString != null) {
Expand Down Expand Up @@ -841,10 +844,10 @@ protected Set<ItemAttributesRQ> extractAttributes(List<Tag> tags) {
*/
@Nullable
protected Set<ItemAttributesRQ> getAttributes(@Nonnull TestStep testStep) {
Field definitionMatchField = getDefinitionMatchField(testStep);
if (definitionMatchField != null) {
Object definitionMatch = getDefinitionMatch(testStep);
if (definitionMatch != null) {
try {
Method method = retrieveMethod(definitionMatchField, testStep);
Method method = retrieveMethod(definitionMatch);
Attributes attributesAnnotation = method.getAnnotation(Attributes.class);
if (attributesAnnotation != null) {
return AttributeParser.retrieveAttributes(attributesAnnotation);
Expand All @@ -864,9 +867,8 @@ protected Set<ItemAttributesRQ> getAttributes(@Nonnull TestStep testStep) {
*/
@Nullable
protected String getCodeRef(@Nonnull TestStep testStep) {
return ofNullable(getDefinitionMatchField(testStep)).flatMap(match -> {
return ofNullable(getDefinitionMatch(testStep)).flatMap(stepDefinitionMatch -> {
try {
StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) match.get(testStep);
Field stepDefinitionField = stepDefinitionMatch.getClass().getDeclaredField(STEP_DEFINITION_FIELD_NAME);
stepDefinitionField.setAccessible(true);
Object javaStepDefinition = stepDefinitionField.get(stepDefinitionMatch);
Expand Down Expand Up @@ -908,10 +910,10 @@ protected String getCodeRef(@Nonnull String uri, int line) {
@Nullable
@SuppressWarnings("unchecked")
protected TestCaseIdEntry getTestCaseId(@Nonnull TestStep testStep, @Nullable String codeRef) {
Field definitionMatchField = getDefinitionMatchField(testStep);
if (definitionMatchField != null) {
Object definitionMatch = getDefinitionMatch(testStep);
if (definitionMatch != null) {
try {
Method method = retrieveMethod(definitionMatchField, testStep);
Method method = retrieveMethod(definitionMatch);
return TestCaseIdUtils.getTestCaseId(method.getAnnotation(TestCaseId.class),
method,
codeRef,
Expand Down Expand Up @@ -954,7 +956,7 @@ protected List<ParameterResource> getParameters(@Nullable String codeRef, @Nonnu
if (arg instanceof PickleString) {
value = ((PickleString) arg).getContent();
} else if (arg instanceof PickleTable) {
value = formatDataTable(((PickleTable) arg).getRows()
value = MarkdownUtils.formatDataTable(((PickleTable) arg).getRows()
.stream()
.map(r -> r.getCells().stream().map(PickleCell::getValue).collect(Collectors.toList()))
.collect(Collectors.toList()));
Expand Down Expand Up @@ -1000,18 +1002,13 @@ protected String getDescription(@Nonnull Feature feature, @Nonnull String uri) {
*/
@Nonnull
protected Pair<String, String> getHookTypeAndName(@Nonnull HookType hookType) {
String name = null;
String type = null;
switch (hookType) {
case Before:
name = "Before hooks";
type = "BEFORE_TEST";
break;
return Pair.of(ItemType.BEFORE_TEST.name(), "Before hooks");
case After:
name = "After hooks";
type = "AFTER_TEST";
break;
return Pair.of(ItemType.AFTER_TEST.name(), "After hooks");
default:
return Pair.of(ItemType.TEST.name(), "Hook");
}
return Pair.of(type, name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.epam.reportportal.cucumber;

import com.epam.reportportal.listeners.ItemType;
import com.epam.reportportal.utils.MemoizingSupplier;
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
import cucumber.api.HookType;
Expand Down Expand Up @@ -46,9 +47,9 @@
* @author Serhii Zharskyi
*/
public class ScenarioReporter extends AbstractReporter {
private static final String RP_STORY_TYPE = "SUITE";
private static final String RP_TEST_TYPE = "STORY";
private static final String RP_STEP_TYPE = "STEP";
private static final String RP_STORY_TYPE = ItemType.SUITE.name();
private static final String RP_TEST_TYPE = ItemType.STORY.name();
private static final String RP_STEP_TYPE = ItemType.STEP.name();

protected MemoizingSupplier<Maybe<String>> rootSuiteId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.epam.reportportal.cucumber;

import com.epam.reportportal.listeners.ItemType;
import io.reactivex.Maybe;

import javax.annotation.Nonnull;
Expand All @@ -36,12 +37,12 @@
* created in hooks will be attached to these, and not to the actual failing
* steps!)
*
* @author Sergey_Gvozdyukevich
* @author Serhii Zharskyi
* @deprecated Use {@link ScenarioReporter}, since the semantic of this class is completely broken and will be removed
*/
@Deprecated
public class StepReporter extends AbstractReporter {
private static final String RP_STORY_TYPE = "STORY";
private static final String RP_TEST_TYPE = "SCENARIO";
private static final String RP_STORY_TYPE = ItemType.STORY.name();
private static final String RP_TEST_TYPE = ItemType.SCENARIO.name();

@Override
@Nonnull
Expand Down
124 changes: 30 additions & 94 deletions src/main/java/com/epam/reportportal/cucumber/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,46 @@
package com.epam.reportportal.cucumber;

import com.epam.reportportal.listeners.ItemStatus;
import com.google.common.collect.ImmutableMap;
import com.epam.reportportal.listeners.LogLevel;
import com.epam.reportportal.utils.reflect.Accessible;
import cucumber.api.Result;
import cucumber.api.TestStep;
import cucumber.runtime.StepDefinitionMatch;
import io.reactivex.annotations.Nullable;

import javax.annotation.Nonnull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static java.util.Optional.ofNullable;

public class Utils {
private static final String DEFINITION_MATCH_FIELD_NAME = "definitionMatch";
private static final String STEP_DEFINITION_FIELD_NAME = "stepDefinition";
private static final String METHOD_FIELD_NAME = "method";
public static final String ONE_SPACE = "\u00A0";
private static final String NEW_LINE = "\r\n";
public static final String TABLE_INDENT = "\u00A0\u00A0\u00A0\u00A0";
public static final String TABLE_COLUMN_SEPARATOR = "|";
public static final String TABLE_ROW_SEPARATOR = "-";

private Utils() {
throw new RuntimeException("No instances should exist for the class!");
}

//@formatter:off
public static final Map<Result.Type, ItemStatus> STATUS_MAPPING = ImmutableMap.<Result.Type, ItemStatus>builder()
.put(Result.Type.PASSED, ItemStatus.PASSED)
.put(Result.Type.FAILED, ItemStatus.FAILED)
.put(Result.Type.SKIPPED, ItemStatus.SKIPPED)
.put(Result.Type.PENDING, ItemStatus.SKIPPED)
.put(Result.Type.UNDEFINED, ItemStatus.SKIPPED)
.put(Result.Type.AMBIGUOUS, ItemStatus.SKIPPED).build();

public static final Map<Result.Type, String> LOG_LEVEL_MAPPING = ImmutableMap.<Result.Type, String>builder()
.put(Result.Type.PASSED, "INFO")
.put(Result.Type.FAILED, "ERROR")
.put(Result.Type.SKIPPED, "WARN")
.put(Result.Type.PENDING, "WARN")
.put(Result.Type.UNDEFINED, "WARN")
.put(Result.Type.AMBIGUOUS, "WARN").build();
public static final Map<Result.Type, ItemStatus> STATUS_MAPPING = Collections.unmodifiableMap(new HashMap<Result.Type, ItemStatus>(){{
put(Result.Type.PASSED, ItemStatus.PASSED);
put(Result.Type.FAILED, ItemStatus.FAILED);
put(Result.Type.SKIPPED, ItemStatus.SKIPPED);
put(Result.Type.PENDING, ItemStatus.SKIPPED);
put(Result.Type.UNDEFINED, ItemStatus.SKIPPED);
put(Result.Type.AMBIGUOUS, ItemStatus.SKIPPED);
}});

public static final Map<Result.Type, String> LOG_LEVEL_MAPPING = Collections.unmodifiableMap(new HashMap<Result.Type, String>(){{
put(Result.Type.PASSED, LogLevel.INFO.name());
put(Result.Type.FAILED, LogLevel.ERROR.name());
put(Result.Type.SKIPPED, LogLevel.WARN.name());
put(Result.Type.PENDING, LogLevel.WARN.name());
put(Result.Type.UNDEFINED, LogLevel.WARN.name());
put(Result.Type.AMBIGUOUS, LogLevel.WARN.name());
}});
//@formatter:on

/**
Expand All @@ -76,82 +70,24 @@ public static String buildName(String prefix, String infix, String argument) {
return (prefix == null ? "" : prefix) + infix + argument;
}

public static Method retrieveMethod(Field definitionMatchField, TestStep testStep) throws NoSuchFieldException, IllegalAccessException {
StepDefinitionMatch stepDefinitionMatch = (StepDefinitionMatch) definitionMatchField.get(testStep);
Field stepDefinitionField = stepDefinitionMatch.getClass().getDeclaredField(STEP_DEFINITION_FIELD_NAME);
stepDefinitionField.setAccessible(true);
Object javaStepDefinition = stepDefinitionField.get(stepDefinitionMatch);
Field methodField = javaStepDefinition.getClass().getDeclaredField(METHOD_FIELD_NAME);
methodField.setAccessible(true);
return (Method) methodField.get(javaStepDefinition);
public static Method retrieveMethod(Object stepDefinitionMatch) throws IllegalAccessException, NoSuchFieldException {
Object javaStepDefinition = Accessible.on(stepDefinitionMatch).field(STEP_DEFINITION_FIELD_NAME).getValue();
Method method = null;
if (javaStepDefinition != null) {
method = (Method) Accessible.on(javaStepDefinition).field(METHOD_FIELD_NAME).getValue();
}
return method;
}

public static final java.util.function.Function<List<cucumber.runtime.Argument>, List<?>> ARGUMENTS_TRANSFORM = arguments -> ofNullable(
arguments).map(args -> args.stream().map(cucumber.runtime.Argument::getVal).collect(Collectors.toList())).orElse(null);

@Nullable
public static Field getDefinitionMatchField(@Nonnull TestStep testStep) {
Class<?> clazz = testStep.getClass();

public static Object getDefinitionMatch(@Nonnull TestStep testStep) {
try {
return clazz.getField(DEFINITION_MATCH_FIELD_NAME);
return Accessible.on(testStep).field(DEFINITION_MATCH_FIELD_NAME).getValue();
} catch (NoSuchFieldException e) {
do {
try {
Field definitionMatchField = clazz.getDeclaredField(DEFINITION_MATCH_FIELD_NAME);
definitionMatchField.setAccessible(true);
return definitionMatchField;
} catch (NoSuchFieldException ignore) {
}

clazz = clazz.getSuperclass();
} while (clazz != null);

return null;
}
}

/**
* Converts a table represented as List of Lists to a formatted table string
*
* @param table a table object
* @return string representation of the table
*/
@Nonnull
public static String formatDataTable(@Nonnull final List<List<String>> table) {
StringBuilder result = new StringBuilder();
int tableLength = table.stream().mapToInt(List::size).max().orElse(-1);
List<Iterator<String>> iterList = table.stream().map(List::iterator).collect(Collectors.toList());
List<Integer> colSizes = IntStream.range(0, tableLength)
.mapToObj(n -> iterList.stream().filter(Iterator::hasNext).map(Iterator::next).collect(Collectors.toList()))
.map(col -> col.stream().mapToInt(String::length).max().orElse(0))
.collect(Collectors.toList());

boolean header = true;
for (List<String> row : table) {
result.append(TABLE_INDENT).append(TABLE_COLUMN_SEPARATOR);
for (int i = 0; i < row.size(); i++) {
String cell = row.get(i);
int maxSize = colSizes.get(i) - cell.length() + 2;
int lSpace = maxSize / 2;
int rSpace = maxSize - lSpace;
IntStream.range(0, lSpace).forEach(j -> result.append(ONE_SPACE));
result.append(cell);
IntStream.range(0, rSpace).forEach(j -> result.append(ONE_SPACE));
result.append(TABLE_COLUMN_SEPARATOR);
}
if (header) {
header = false;
result.append(NEW_LINE);
result.append(TABLE_INDENT).append(TABLE_COLUMN_SEPARATOR);
for (int i = 0; i < row.size(); i++) {
int maxSize = colSizes.get(i) + 2;
IntStream.range(0, maxSize).forEach(j -> result.append(TABLE_ROW_SEPARATOR));
result.append(TABLE_COLUMN_SEPARATOR);
}
}
result.append(NEW_LINE);
}
return result.toString().trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.util.test.CommonUtils;
import com.epam.reportportal.utils.markdown.MarkdownUtils;
import com.epam.ta.reportportal.ws.model.ParameterResource;
import com.epam.ta.reportportal.ws.model.StartTestItemRQ;
import com.epam.ta.reportportal.ws.model.log.SaveLogRQ;
Expand Down Expand Up @@ -73,7 +74,7 @@ public static class DataTableParameterTest extends AbstractTestNGCucumberTests {
}

private static final String DOCSTRING_PARAM = "My very long parameter\nWith some new lines";
private static final String TABLE_PARAM = Utils.formatDataTable(Arrays.asList(Arrays.asList("key", "value"),
private static final String TABLE_PARAM = MarkdownUtils.formatDataTable(Arrays.asList(Arrays.asList("key", "value"),
Arrays.asList("myKey", "myValue")
));

Expand Down
Loading