Skip to content

Commit 8e242a7

Browse files
yholiabaev
authored andcommitted
add ability to attach selenium logs in case of test failure (via #360)
1 parent 9aa3be0 commit 8e242a7

4 files changed

Lines changed: 147 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ Listener for Selenide, that logging steps for Allure:
7070
Usage example:
7171
```
7272
SelenideLogger.addListener("AllureSelenide", new AllureSelenide().screenshots(true).savePageSource(false));
73+
74+
Capture selenium logs:
75+
SelenideLogger.addListener("AllureSelenide", new AllureSelenide().enableLogs(LogType.BROWSER, Level.ALL));
76+
https://github.com/SeleniumHQ/selenium/wiki/Logging
7377
```
7478

7579

allure-selenide/src/main/java/io/qameta/allure/selenide/AllureSelenide.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.qameta.allure.selenide;
1717

18+
import com.codeborne.selenide.Selenide;
1819
import com.codeborne.selenide.WebDriverRunner;
1920
import com.codeborne.selenide.logevents.LogEvent;
2021
import com.codeborne.selenide.logevents.LogEventListener;
@@ -29,8 +30,11 @@
2930
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
3132

33+
import java.util.HashMap;
34+
import java.util.Map;
3235
import java.util.Optional;
3336
import java.util.UUID;
37+
import java.util.logging.Level;
3438

3539
import static io.qameta.allure.util.ResultsUtils.getStatus;
3640
import static io.qameta.allure.util.ResultsUtils.getStatusDetails;
@@ -46,7 +50,7 @@ public class AllureSelenide implements LogEventListener {
4650

4751
private boolean saveScreenshots = true;
4852
private boolean savePageHtml = true;
49-
53+
private final Map<LogType, Level> logTypesToSave = new HashMap<>();
5054
private final AllureLifecycle lifecycle;
5155

5256
public AllureSelenide() {
@@ -67,6 +71,18 @@ public AllureSelenide savePageSource(final boolean savePageHtml) {
6771
return this;
6872
}
6973

74+
public AllureSelenide enableLogs(final LogType logType, final Level logLevel) {
75+
logTypesToSave.put(logType, logLevel);
76+
77+
return this;
78+
}
79+
80+
public AllureSelenide disableLogs(final LogType logType) {
81+
logTypesToSave.remove(logType);
82+
83+
return this;
84+
}
85+
7086
private static Optional<byte[]> getScreenshotBytes() {
7187
try {
7288
return WebDriverRunner.hasWebDriverStarted()
@@ -89,6 +105,10 @@ private static Optional<byte[]> getPageSourceBytes() {
89105
}
90106
}
91107

108+
private static String getBrowserLogs(final LogType logType, final Level level) {
109+
return String.join("\n\n", Selenide.getWebDriverLogs(logType.toString(), level));
110+
}
111+
92112
@Override
93113
public void beforeEvent(final LogEvent event) {
94114
lifecycle.getCurrentTestCaseOrStep().ifPresent(parentUuid -> {
@@ -113,6 +133,13 @@ public void afterEvent(final LogEvent event) {
113133
getPageSourceBytes()
114134
.ifPresent(bytes -> lifecycle.addAttachment("Page source", "text/html", "html", bytes));
115135
}
136+
if (!logTypesToSave.isEmpty()) {
137+
logTypesToSave
138+
.forEach((logType, level) -> {
139+
final byte[] content = getBrowserLogs(logType, level).getBytes(UTF_8);
140+
lifecycle.addAttachment("Logs from: " + logType, "application/json", ".txt", content);
141+
});
142+
}
116143
lifecycle.updateStep(stepResult -> {
117144
stepResult.setStatus(getStatus(event.getError()).orElse(Status.BROKEN));
118145
stepResult.setStatusDetails(getStatusDetails(event.getError()).orElse(new StatusDetails()));
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2019 Qameta Software OÜ
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.selenide;
17+
18+
/**
19+
* Enum wrapper of Selenium {@link org.openqa.selenium.logging.LogType}.
20+
21+
* @author Yevhen Holiakhovskyi.
22+
*/
23+
public enum LogType {
24+
25+
/**
26+
* This log type pertains to logs from the browser.
27+
*/
28+
BROWSER(org.openqa.selenium.logging.LogType.BROWSER),
29+
30+
/**
31+
* This log type pertains to logs from the client.
32+
*/
33+
CLIENT(org.openqa.selenium.logging.LogType.CLIENT),
34+
35+
/**
36+
* This log pertains to logs from the WebDriver implementation.
37+
*/
38+
DRIVER(org.openqa.selenium.logging.LogType.DRIVER),
39+
40+
/**
41+
* This log type pertains to logs relating to performance timings.
42+
*/
43+
PERFORMANCE(org.openqa.selenium.logging.LogType.PERFORMANCE),
44+
45+
/**
46+
* This log type pertains to logs relating to performance timings.
47+
*/
48+
PROFILER(org.openqa.selenium.logging.LogType.PROFILER),
49+
50+
/**
51+
* This log type pertains to logs from the remote server.
52+
*/
53+
SERVER(org.openqa.selenium.logging.LogType.SERVER);
54+
55+
private final String logType;
56+
57+
LogType(final String logType) {
58+
this.logType = logType;
59+
}
60+
61+
@Override
62+
public String toString() {
63+
return logType;
64+
}
65+
}

allure-selenide/src/test/java/io/qameta/allure/selenide/AllureSelenideTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,16 @@
3131
import org.junit.jupiter.api.Test;
3232
import org.openqa.selenium.OutputType;
3333
import org.openqa.selenium.WebDriverException;
34+
import org.openqa.selenium.WebDriver.Options;
3435
import org.openqa.selenium.chrome.ChromeDriver;
36+
import org.openqa.selenium.logging.LogEntries;
37+
import org.openqa.selenium.logging.LogEntry;
38+
import org.openqa.selenium.logging.Logs;
3539

3640
import java.nio.charset.StandardCharsets;
41+
import java.util.Collections;
3742
import java.util.UUID;
43+
import java.util.logging.Level;
3844

3945
import static io.qameta.allure.test.RunUtils.runWithinTestContext;
4046
import static org.assertj.core.api.Assertions.assertThat;
@@ -208,6 +214,50 @@ void shouldNotFailIfBrowserIsNotOpened() {
208214
assertThat(selenideStep.getAttachments()).hasSize(0);
209215
}
210216

217+
@AllureFeatures.Attachments
218+
@Test
219+
void shouldSaveLogs() {
220+
final LogEntry logEntry = new LogEntry(Level.ALL, 10, "SIMPLE LOG");
221+
final LogEntries logEntries = new LogEntries(Collections.singletonList(logEntry));
222+
final ChromeDriver wdMock = mock(ChromeDriver.class);
223+
final Logs logsMock = mock(Logs.class);
224+
final Options optionsMock = mock(Options.class);
225+
226+
WebDriverRunner.setWebDriver(wdMock);
227+
228+
doReturn(optionsMock).when(wdMock).manage();
229+
doReturn(logsMock).when(optionsMock).logs();
230+
doReturn(logEntries).when(logsMock).get(LogType.BROWSER.toString());
231+
232+
final AllureResults results = runWithinTestContext(() -> {
233+
final AllureSelenide selenide = new AllureSelenide()
234+
.enableLogs(LogType.BROWSER, Level.ALL)
235+
.savePageSource(false)
236+
.screenshots(false);
237+
238+
SelenideLogger.addListener(UUID.randomUUID().toString(), selenide);
239+
240+
final SelenideLog log = SelenideLogger.beginStep(
241+
"dummy source",
242+
"dummyMethod()",
243+
"param1",
244+
"param2");
245+
246+
SelenideLogger.commitStep(log, new Exception("something went wrong"));
247+
});
248+
249+
final StepResult selenideStep = extractStepFromResults(results);
250+
final Attachment attachment = selenideStep.getAttachments().iterator().next();
251+
final String attachmentContent = new String(
252+
results.getAttachments().get(attachment.getSource()),
253+
StandardCharsets.UTF_8
254+
);
255+
256+
assertThat(selenideStep.getAttachments()).hasSize(1);
257+
assertThat(results.getAttachments()).containsKey(attachment.getSource());
258+
assertThat(attachmentContent).isEqualTo(logEntry.toString());
259+
}
260+
211261
@AllureFeatures.Steps
212262
@Test
213263
void shouldLogFailedSteps() {

0 commit comments

Comments
 (0)