I have been trying to make LeanFT html reports work with my Selenium/Junit framework, however so far without any joy. I have searched the topic multiple times on different forums incl. HP official materials and tried all setup methods that I could find. An XML runresults file is still generated when using a custom Selenium/LeanFT framework.
I create a LeanFT Testing Project project using JUnit as my framework and Selenium as SDK. I also add relevant Selenium jars.
LeanFT version is 14.0.2816.0. I am conscious of this issue: https://community.softwaregrp.com/t5/UFT-Practitioners-Forum/HTML-report-not-generated-in-custom-framework-using-LeanFT/td-p/1614027 .
I would be grateful, if someone could explain where I am making a mistake here or if the software version is the problem here. Any help is very much appreciated.
The actual setup contains more abstractions, is generally more complex and runs as a jar file, but I have simplified the code for the purpose of this topic as the outcome of both setups is the same - a runresults.xml and no html:
Test Class:
import com.hp.lft.report.CaptureLevel;
import com.hp.lft.report.ModifiableReportConfiguration;
import com.hp.lft.report.Reporter;
import com.hp.lft.sdk.ModifiableSDKConfiguration;
import com.hp.lft.sdk.SDK;
import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserDescription;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;
import core.Selenium;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.*;
import java.io.File;
import java.net.URI;
public class SeleniumTest extends Selenium {
WebDriver driver;
Browser browser;
public SeleniumTest() {
//Change this constructor to private if you supply your own public constructor
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
instance = new SeleniumTest();
globalSetup(SeleniumTest.class);
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
globalTearDown();
}
@Before
public void setUp() throws Exception {
ModifiableSDKConfiguration sdkConfig = new ModifiableSDKConfiguration();
sdkConfig.setServerAddress(new URI("ws://localhost:5095"));
SDK.init(sdkConfig);
ModifiableReportConfiguration reportConfig = new ModifiableReportConfiguration();
reportConfig.setOverrideExisting(true);
reportConfig.setTargetDirectory("C:\\Users\\user\\IdeaProjects\\LeanFT_Selenium\\RunResults");
reportConfig.setReportFolder("LastRun");
reportConfig.setTitle("Summary");
reportConfig.setDescription("Description");
reportConfig.setSnapshotsLevel(CaptureLevel.All);
Reporter.init(reportConfig);
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File
("C:\\Program Files (x86)\\HP\\Unified Functional Testing\\Installations\\Chrome\\Agent.crx"));
System.setProperty("webdriver.chrome.driver",
"C:\\HP_Reporting\\Webdriver\\chromedriver.exe");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(options);
browser = BrowserFactory.attach(new BrowserDescription.Builder()
.type(BrowserType.CHROME).build());
}
@After
public void tearDown() throws Exception {
driver.quit();
browser = null;
Reporter.generateReport();
SDK.cleanup();
}
@Test
public void test() throws Exception {
driver.get("https://www.google.co.uk/");
}
}
Selenium Class:
import com.hp.lft.report.Status;
import com.hp.lft.unittesting.UnitTestBase;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
public class Selenium extends UnitTestBase{
protected static Selenium instance;
public static void globalSetup(Class<? extends Selenium> testClass) throws Exception {
if (instance == null)
instance = testClass.newInstance();
instance.classSetup();
}
@Before
public void beforeTest() throws Exception {
testSetup();
}
@After
public void afterTest() throws Exception {
testTearDown();
}
public static void globalTearDown() throws Exception {
instance.classTearDown();
getReporter().generateReport();
}
@ClassRule
public static TestWatcher classWatcher = new TestWatcher() {
@Override
protected void starting(org.junit.runner.Description description) {
className = description.getClassName();
}
};
@Rule
public TestWatcher watcher = new TestWatcher() {
@Override
protected void starting(org.junit.runner.Description description) {
testName = description.getMethodName();
}
@Override
protected void failed(Throwable e, org.junit.runner.Description description) {
setStatus(Status.Failed);
}
@Override
protected void succeeded(org.junit.runner.Description description) {
setStatus(Status.Passed);
}
};
@Override
protected String getTestName() {
return testName;
}
@Override
protected String getClassName() {
return className;
}
protected static String className;
protected String testName;
}
The report is only generated in 14.00 by extending UnitTestBase
. To have the report generated with a custom automation framework, you must upgrade to at least LeanFT 14.01 (latest one at the time of writting is 14.02 though).
Oh, and just for clarification: this issue has nothing to do with Selenium. You'd have the same behavior in C# LeanFT SDK using NUnit 3, for example.
What is a custom automation framework in this context?
When I say custom automation framework I mean any framework that does the SDK
and Reporter
initialization and cleanup itself.
LeanFT does all the magic through its engine. To tell a custom framework to connect to the engine, you need perform the following steps:
at the beginning of a test suite:
SDK.init();
Reporter.init(); // This is not for the engine, but for the HTML report generation
at the end of a test suite
Reporter.generateReport();
SDK.cleanup();
When you are using the builtin templates, you'll notice that a UnitTestClassBase
class is automatically created, that extends from UnitTestBase
and that your LeanFtTest
class extends from this UnitTestClassBase
.
By doing so you are initializing the SDK
and the Reporter
in a very specific way, which is the reason why with this initialization the HTML report is generated. If you were to reproduce this specific way in your custom framework, you'll also have the HTML report generated. If you are curious, you can check the contents of the UnitTestBase.class
file to see what it does.
You are extending from UnitTestBase. Why is it not working?
As mentioned in my comments, you are actually doing the SDK
and Reporter
initialization twice, once by extending the UnitTestBase
(which, as I described above, does that initialization already) and the second time in your setUp
method.
Since you are using LeanFT 14.00, you should let the UnitTestBase
do the initialization, cleanup and report generation. This means that your Test Class file should be changed to no longer include the init of the SDK
and Reporter
, as follows:
import com.hp.lft.report.CaptureLevel;
import com.hp.lft.report.ModifiableReportConfiguration;
import com.hp.lft.report.Reporter;
import com.hp.lft.sdk.ModifiableSDKConfiguration;
import com.hp.lft.sdk.SDK;
import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserDescription;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;
import core.Selenium;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.*;
import java.io.File;
import java.net.URI;
public class SeleniumTest extends Selenium {
WebDriver driver;
Browser browser;
public SeleniumTest() {
//Change this constructor to private if you supply your own public constructor
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
instance = new SeleniumTest();
globalSetup(SeleniumTest.class);
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
globalTearDown();
}
@Before
public void setUp() throws Exception {
/*
This will not work in LeanFT 14.00, so we are commenting it out
ModifiableSDKConfiguration sdkConfig = new ModifiableSDKConfiguration();
sdkConfig.setServerAddress(new URI("ws://localhost:5095"));
SDK.init(sdkConfig);
ModifiableReportConfiguration reportConfig = new ModifiableReportConfiguration();
reportConfig.setOverrideExisting(true);
reportConfig.setTargetDirectory("C:\\Users\\user\\IdeaProjects\\LeanFT_Selenium\\RunResults");
reportConfig.setReportFolder("LastRun");
reportConfig.setTitle("Summary");
reportConfig.setDescription("Description");
reportConfig.setSnapshotsLevel(CaptureLevel.All);
Reporter.init(reportConfig);
*/
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File
("C:\\Program Files (x86)\\HP\\Unified Functional Testing\\Installations\\Chrome\\Agent.crx"));
System.setProperty("webdriver.chrome.driver",
"C:\\HP_Reporting\\Webdriver\\chromedriver.exe");
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(options);
browser = BrowserFactory.attach(new BrowserDescription.Builder()
.type(BrowserType.CHROME).build());
}
@After
public void tearDown() throws Exception {
driver.quit();
browser = null;
//Reporter.generateReport();
//SDK.cleanup();
}
@Test
public void test() throws Exception {
driver.get("https://www.google.co.uk/");
}
}
But I need to configure the SDK and the Report. How can I achieve that in LeanFT 14.00?
The SDK
and the Reporter
can be configured in two ways:
ModifiableSDKConfiguration
and ModifiableReportConfiguration
or
resources/leanft.properties
). You can see plenty details in the official help.You can manipulate some report settings at runtime as well, through the Reporter
API:
Reporter.setReportLevel(ReportLevel.All);
Reporter.setSnapshotCaptureLevel(CaptureLevel.All);
SDK
and the Reporter
through the base class, you can still add custom report events in the report (these work: Reporter.reportEvent();
, Reporter.startReportingContext();
, Reporter.startTest();
, etc.)