Skip to content

Commit

Permalink
Merge pull request #49 from reportportal/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
HardNorth authored Jan 21, 2025
2 parents 11b7267 + 2705d90 commit b036910
Show file tree
Hide file tree
Showing 25 changed files with 288 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
java-version: '8'

- name: Setup git credentials
uses: oleksiyrudenko/gha-git-credentials@v2.1.1
uses: oleksiyrudenko/gha-git-credentials@v2-latest
with:
name: 'reportportal.io'
email: '[email protected]'
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## [Unreleased]
### Added
- Putting last error logs of tests to Items' description, by @YevhenPiskun
### Changed
- Client version updated on [5.2.25](https://github.com/reportportal/client-java/releases/tag/5.2.25), by @HardNorth

## [5.2.3]
### Changed
Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,22 @@ repositories {
}

dependencies {
api "com.epam.reportportal:client-java:5.2.13"
api "com.epam.reportportal:client-java:5.2.25"

compileOnly "org.spockframework:spock-core:${spock_version}"
implementation 'org.slf4j:slf4j-api:2.0.7'

testImplementation "org.spockframework:spock-core:${spock_version}"
testImplementation 'org.codehaus.groovy:groovy:2.5.14'
testImplementation 'com.epam.reportportal:agent-java-test-utils:0.0.6'
testImplementation 'com.epam.reportportal:agent-java-test-utils:0.0.7'

testImplementation 'org.aspectj:aspectjweaver:1.9.19'
testImplementation 'org.hamcrest:hamcrest-core:2.2'
testImplementation "org.mockito:mockito-core:${mockito_version}"
testImplementation "org.mockito:mockito-inline:${mockito_version}"
testImplementation "org.mockito:mockito-junit-jupiter:${mockito_version}"
testImplementation 'ch.qos.logback:logback-classic:1.3.12'
testImplementation 'com.epam.reportportal:logger-java-logback:5.2.2'
testImplementation 'ch.qos.logback:logback-classic:1.3.15'
testImplementation 'com.epam.reportportal:logger-java-logback:5.2.3'
testImplementation ("org.junit.platform:junit-platform-runner:${junit5_launcher_version}") {
exclude module: 'junit'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
import com.epam.reportportal.service.item.TestCaseIdEntry;
import com.epam.reportportal.spock.utils.SystemAttributesFetcher;
import com.epam.reportportal.utils.*;
import com.epam.reportportal.utils.formatting.ExceptionUtils;
import com.epam.reportportal.utils.formatting.MarkdownUtils;
import com.epam.ta.reportportal.ws.model.FinishExecutionRQ;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
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 io.reactivex.Maybe;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.codehaus.groovy.runtime.StackTraceUtils;
import org.slf4j.Logger;
Expand All @@ -44,6 +47,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
Expand Down Expand Up @@ -74,6 +78,7 @@ public class ReportPortalSpockListener extends AbstractRunListener {
.orElseThrow(() -> new IllegalStateException("Unknown Spock version.")));

private final MemoizingSupplier<Launch> launch;
private final Map<Maybe<String>, Pair<String, String>> errorDescriptionMap = new ConcurrentHashMap<>();

// stores the bindings of Spock method kinds to the RP-specific notation
private static final Map<MethodKind, String> ITEM_TYPES_REGISTRY = Collections.unmodifiableMap(new HashMap<MethodKind, String>() {{
Expand Down Expand Up @@ -138,7 +143,8 @@ public Maybe<String> startLaunch() {
launchContext.setLaunchId(launchId);
return launchId;
} catch (ReportPortalException ex) {
handleRpException(ex,
handleRpException(
ex,
"Unable start the launch: '" + ofNullable(launchParameters).map(ListenerParameters::getLaunchName)
.orElse("Unknown Launch") + "'"
);
Expand Down Expand Up @@ -210,9 +216,11 @@ protected Maybe<String> startFixture(@Nonnull Maybe<String> parentId, @Nonnull S
public void registerFixture(SpecInfo spec, @Nonnull FeatureInfo feature, IterationInfo iteration, @Nonnull MethodInfo fixture) {
NodeFootprint<SpecInfo> specFootprint = launchContext.findSpecFootprint(spec);
StartTestItemRQ rq = buildFixtureItemRq(feature, fixture, !fixture.getParent().equals(specFootprint.getItem()));
Maybe<String> testItemId = startFixture(rq.isHasStats() ?
specFootprint.getId() :
launchContext.findFeatureFootprint(feature).getId(), rq);
Maybe<String> testItemId = startFixture(
rq.isHasStats() ?
specFootprint.getId() :
launchContext.findFeatureFootprint(feature).getId(), rq
);
@SuppressWarnings("rawtypes")
NodeFootprint<? extends NodeInfo> fixtureOwnerFootprint = findFixtureOwner(spec, feature, iteration, fixture);
fixtureOwnerFootprint.addFixtureFootprint(new FixtureFootprint(fixture, testItemId));
Expand Down Expand Up @@ -259,7 +267,8 @@ protected StartTestItemRQ buildIterationItemRq(@Nonnull IterationInfo iteration)
.orElse(null));
List<Object> paramList = ofNullable(params).orElse(Collections.emptyList());
List<String> names = iteration.getFeature().getParameterNames();
rq.setParameters(ParameterUtils.getParameters(codeRef,
rq.setParameters(ParameterUtils.getParameters(
codeRef,
IntStream.range(0, paramList.size()).mapToObj(i -> Pair.of(names.get(i), paramList.get(i))).collect(Collectors.toList())
));
setFeatureAttributes(rq, iteration.getFeature());
Expand All @@ -274,16 +283,19 @@ protected Maybe<String> startIteration(@Nonnull Maybe<String> parentId, @Nonnull
protected void reportIterationStart(@Nonnull Maybe<String> parentId, @Nonnull StartTestItemRQ rq, @Nonnull IterationInfo iteration) {
Maybe<String> testItemId = startIteration(parentId, rq);
launchContext.addRunningIteration(testItemId, iteration);
errorDescriptionMap.put(launchContext.findIterationFootprint(iteration).getId(), Pair.of(rq.getDescription(), StringUtils.EMPTY));
}

public void registerIteration(@Nonnull IterationInfo iteration) {
if (iteration.getFeature().isReportIterations()) {
reportIterationStart(launchContext.findSpecFootprint(iteration.getFeature().getSpec()).getId(),
reportIterationStart(
launchContext.findSpecFootprint(iteration.getFeature().getSpec()).getId(),
buildIterationItemRq(iteration),
iteration
);
} else if (iteration.getFeature().isParameterized()) {
reportIterationStart(launchContext.findFeatureFootprint(iteration.getFeature()).getId(),
reportIterationStart(
launchContext.findFeatureFootprint(iteration.getFeature()).getId(),
buildNestedIterationItemRq(iteration),
iteration
);
Expand All @@ -303,6 +315,15 @@ protected FinishTestItemRQ buildFinishTestItemRq(@Nonnull Maybe<String> itemId,
FinishTestItemRQ rq = new FinishTestItemRQ();
ofNullable(status).ifPresent(s -> rq.setStatus(s.name()));
rq.setEndTime(Calendar.getInstance().getTime());
if (Objects.equals(status, ItemStatus.FAILED) && errorDescriptionMap.containsKey(itemId)) {
String formattedException = String.format("Error:\n%s", errorDescriptionMap.get(itemId).getRight());
if (StringUtils.isNotBlank(errorDescriptionMap.get(itemId).getLeft())) {
rq.setDescription(MarkdownUtils.asTwoParts(errorDescriptionMap.get(itemId).getLeft(), formattedException));
} else {
rq.setDescription(String.format(formattedException));
}
}
errorDescriptionMap.remove(itemId);
return rq;
}

Expand Down Expand Up @@ -439,6 +460,13 @@ public void reportError(@Nonnull ErrorInfo error) {
ofNullable(launchContext.findFeatureFootprint(method.getFeature())).ifPresent(f -> f.setStatus(FAILED));
ofNullable(launchContext.getRuntimePointerForSpec(method.getParent())
.getCurrentIteration()).map(launchContext::findIterationFootprint).ifPresent(i -> i.setStatus(FAILED));
Maybe<String> itemId = launchContext.findIterationFootprint(error.getMethod().getIteration()).getId();
String startDescriptions = errorDescriptionMap.get(itemId).getLeft();
Pair<String, String> startFinishDescriptions = Pair.of(
startDescriptions,
ExceptionUtils.getStackTrace(error.getException(), new Throwable())
);
errorDescriptionMap.put(itemId, startFinishDescriptions);
logError(error);
} else if (ITERATION_EXECUTION == kind) {
ofNullable(launchContext.findIterationFootprint(method.getIteration())).ifPresent(i -> i.setStatus(FAILED));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.epam.reportportal.spock.description;

import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.spock.ReportPortalSpockListener;
import com.epam.reportportal.spock.features.fail.HelloSpockSpecFailed;
import com.epam.reportportal.spock.utils.TestExtension;
import com.epam.reportportal.spock.utils.TestUtils;
import com.epam.reportportal.util.test.CommonUtils;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
import org.mockito.ArgumentCaptor;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.epam.reportportal.spock.utils.TestUtils.runClasses;
import static com.epam.reportportal.spock.utils.TestUtils.standardParameters;
import static com.epam.reportportal.spock.utils.TestUtils.testExecutor;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class ConditionNotSatisfiedErrorMessageWithoutDescriptionTest {

private final String classId = CommonUtils.namedId("class_");
private final String methodId = CommonUtils.namedId("method_");
private final List<String> nestedSteps = Stream.generate(() -> CommonUtils.namedId("method_")).limit(3).collect(Collectors.toList());
private final List<Pair<String, String>> nestedStepsLink = nestedSteps.stream().map(s -> Pair.of(methodId, s)).collect(Collectors.toList());

private final ReportPortalClient client = mock(ReportPortalClient.class);

private static final String ERROR_DESCRIPTION = "Error:\nCondition not satisfied:\nname.size() == length\n| | | |\n| 6 | 7\nScotty false\n";


@BeforeEach
public void setupMock() {
TestUtils.mockLaunch(client, null, classId, methodId);
TestUtils.mockNestedSteps(client, nestedStepsLink);
TestUtils.mockBatchLogging(client);
TestExtension.listener = new ReportPortalSpockListener(ReportPortal.create(client, standardParameters(), testExecutor()));
}

@Test
public void verify_error_condition_not_satisfied_message_without_description() {

TestExecutionSummary result = runClasses(HelloSpockSpecFailed.class);

assertThat(result.getTotalFailureCount(), equalTo(1L));

ArgumentCaptor<FinishTestItemRQ> finishNestedStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);
nestedSteps.forEach(s -> verify(client).finishTestItem(eq(s), finishNestedStepCaptor.capture()));

List<FinishTestItemRQ> passedFinishItemStatuses = finishNestedStepCaptor.getAllValues().stream()
.filter(finishTestItemRQ -> finishTestItemRQ.getStatus().equals(ItemStatus.PASSED.name()))
.collect(Collectors.toList());

assertThat(passedFinishItemStatuses, hasSize(2));

passedFinishItemStatuses.forEach(finishTestItemRQ -> assertThat(finishTestItemRQ.getDescription(), is(nullValue())));

List<FinishTestItemRQ> failedFinishItemStatuses = finishNestedStepCaptor.getAllValues().stream()
.filter(finishTestItemRQ -> finishTestItemRQ.getStatus().equals(ItemStatus.FAILED.name()))
.collect(Collectors.toList());

assertThat(failedFinishItemStatuses, hasSize(1));

assertThat(failedFinishItemStatuses.iterator().next().getDescription(), startsWith(ERROR_DESCRIPTION));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.epam.reportportal.spock.description;

import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.spock.ReportPortalSpockListener;
import com.epam.reportportal.spock.features.fail.FailsInDifferentMethod;
import com.epam.reportportal.spock.utils.TestExtension;
import com.epam.reportportal.spock.utils.TestUtils;
import com.epam.reportportal.util.test.CommonUtils;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
import org.mockito.ArgumentCaptor;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.epam.reportportal.spock.utils.TestUtils.runClasses;
import static com.epam.reportportal.spock.utils.TestUtils.standardParameters;
import static com.epam.reportportal.spock.utils.TestUtils.testExecutor;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class ExceptionErrorMessageWithDescriptionTest {

private final String launchId = CommonUtils.namedId("launch_");
private final String classId = CommonUtils.namedId("class_");
private final List<String> methodIds = Stream.generate(() -> CommonUtils.namedId("method_")).limit(1).collect(Collectors.toList());

private final ReportPortalClient client = mock(ReportPortalClient.class);

private static final String ERROR_DESCRIPTION_EXCEPTION = "Setup: \n\n---\n\nError:\njava.lang.IllegalStateException: Some test flow failure";

@BeforeEach
public void setupMock() {
TestUtils.mockLaunch(client, launchId, classId, methodIds);
TestUtils.mockBatchLogging(client);
TestExtension.listener = new ReportPortalSpockListener(ReportPortal.create(client, standardParameters(), testExecutor()));
}

@Test
public void verify_error_exception_message_with_description() {
TestExecutionSummary result = runClasses(FailsInDifferentMethod.class);

assertThat(result.getTotalFailureCount(), equalTo(1L));

ArgumentCaptor<FinishTestItemRQ> finishStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);

methodIds.forEach(s -> verify(client).finishTestItem(eq(s), finishStepCaptor.capture()));

List<FinishTestItemRQ> failedFinishItemStatuses = finishStepCaptor.getAllValues().stream()
.filter(fis -> fis.getStatus().equals(ItemStatus.FAILED.name()))
.collect(Collectors.toList());

assertThat(failedFinishItemStatuses, hasSize(1));
assertThat(failedFinishItemStatuses.iterator().next().getDescription(), startsWith(ERROR_DESCRIPTION_EXCEPTION));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.epam.reportportal.spock.description;

import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.service.ReportPortal;
import com.epam.reportportal.service.ReportPortalClient;
import com.epam.reportportal.spock.ReportPortalSpockListener;
import com.epam.reportportal.spock.features.fail.FailWithExceptionWithoutMessage;
import com.epam.reportportal.spock.utils.TestExtension;
import com.epam.reportportal.spock.utils.TestUtils;
import com.epam.reportportal.util.test.CommonUtils;
import com.epam.ta.reportportal.ws.model.FinishTestItemRQ;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
import org.mockito.ArgumentCaptor;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.epam.reportportal.spock.utils.TestUtils.runClasses;
import static com.epam.reportportal.spock.utils.TestUtils.standardParameters;
import static com.epam.reportportal.spock.utils.TestUtils.testExecutor;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class ExceptionWithoutErrorMessageWithDescriptionTest {

private final String launchId = CommonUtils.namedId("launch_");
private final String classId = CommonUtils.namedId("class_");
private final List<String> methodIds = Stream.generate(() -> CommonUtils.namedId("method_")).limit(1).collect(Collectors.toList());

private final ReportPortalClient client = mock(ReportPortalClient.class);

private static final String ERROR_DESCRIPTION_EXCEPTION = "Setup: \nWhen: \nThen: \n\n---\n\nError:\njava.util.NoSuchElementException";

@BeforeEach
public void setupMock() {
TestUtils.mockLaunch(client, launchId, classId, methodIds);
TestUtils.mockBatchLogging(client);
TestExtension.listener = new ReportPortalSpockListener(ReportPortal.create(client, standardParameters(), testExecutor()));
}

@Test
public void verify_exception_without_error_message_with_description() {
TestExecutionSummary result = runClasses(FailWithExceptionWithoutMessage.class);

assertThat(result.getTotalFailureCount(), equalTo(1L));

ArgumentCaptor<FinishTestItemRQ> finishStepCaptor = ArgumentCaptor.forClass(FinishTestItemRQ.class);

methodIds.forEach(s -> verify(client).finishTestItem(eq(s), finishStepCaptor.capture()));

List<FinishTestItemRQ> failedFinishItemStatuses = finishStepCaptor.getAllValues()
.stream()
.filter(fis -> fis.getStatus().equals(ItemStatus.FAILED.name()))
.collect(Collectors.toList());

assertThat(failedFinishItemStatuses, hasSize(1));
assertThat(failedFinishItemStatuses.iterator().next().getDescription(), startsWith(ERROR_DESCRIPTION_EXCEPTION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public void verify_fail_with_failed_reporting() {

assertThat(result.getTotalFailureCount(), equalTo(1L));

verify(client).getProjectSettings();
verify(client).startLaunch(any());
ArgumentCaptor<StartTestItemRQ> startCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class);
verify(client).startTestItem(any(StartTestItemRQ.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public void verify_fail_with_failed_reporting() {

assertThat(result.getTotalFailureCount(), equalTo(1L));

verify(client).getProjectSettings();
verify(client).startLaunch(any());
ArgumentCaptor<StartTestItemRQ> startCaptor = ArgumentCaptor.forClass(StartTestItemRQ.class);
verify(client).startTestItem(any(StartTestItemRQ.class));
Expand Down
Loading

0 comments on commit b036910

Please sign in to comment.