Cucumber-jvm: Setting up environment before executing any features - java

I want to set environment (e.g. local, dev, prod) once and prior to running any of features.It is to set base url and loading particular test data file. Below is the sample method that I want to invoke once and first thing in my tests. Please suggest the best way to do it.
public void baseSetUp(String environment){
loadTestData = loadPropertiesFile(enviroment);
setBaseUrl(enviroment);
restUtil = new RestUtil(pilotBaseUrl);
initialSetUp();
}
I am newbie to cucumber and java.

The simplest way is to use #Before annotation hooks in the stepDef class for setting up data prior to running the feature file.
import cucumber.annotation.After;
import cucumber.annotation.Before;
#Before
public void baseSetUp(String environment){
loadTestData = loadPropertiesFile(enviroment);
setBaseUrl(enviroment);
restUtil = new RestUtil(pilotBaseUrl);
initialSetUp();
}
#Given("^I am doing step 1$")
public void ...... ...
....
..
.
You can integrate TestNG with Cucumber-JVM , if you want to do more custom actions before and after class/suite/feature step.

I have achieved it by using cucumber with TestNG. In this way, I was able to use annotations of TestNG as well as cucumber hooks. TestNG executes your feature files. Below is the Runner class:
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import cucumber.api.testng.CucumberFeatureWrapper;
import cucumber.api.testng.TestNGCucumberRunner;
import org.junit.runner.RunWith;
import org.testng.annotations.*;
#RunWith(Cucumber.class)
#CucumberOptions(
monochrome = true,
features = "src/test/java/features",
glue = {"utils","steps"},
tags = {"#test"},
format = {
"pretty",
"html:target/cucumber-reports/cucumber-pretty",
"json:target/cucumber-reports/CucumberTestReport.json",
"rerun:target/cucumber-reports/rerun.txt"}
)
public class CucumberRunnerUtil {
private TestNGCucumberRunner testNGCucumberRunner;
#BeforeSuite
public void setUpEnvironment(){
// your setup code e.g. environment set up etc.
}
#BeforeClass(alwaysRun = true)
public void setUpClass() throws Exception {
testNGCucumberRunner = new
TestNGCucumberRunner(this.getClass());
}
#Test(groups = "cucumber", description = "Runs Cucumber Feature",dataProvider = "features" )
public void feature(CucumberFeatureWrapper cucumberFeature) {
testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
}
#DataProvider
public Object[][] features() {
return testNGCucumberRunner.provideFeatures();
}
#AfterClass(alwaysRun = true)
public void tearDownClass() throws Exception {
testNGCucumberRunner.finish();
}
#AfterSuite
public void cleanUp(){
// code to clean resources.
}
}

Related

LeanFT & Selenium custom automation framework - no HTML report generated

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;
}
Libraries
TL;DR
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.
Details
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:
At initialization, as you attempted to do through the ModifiableSDKConfiguration and ModifiableReportConfiguration
or
In the test settings file (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:
Set the report level: Reporter.setReportLevel(ReportLevel.All);
Set the snapshot capture level Reporter.setSnapshotCaptureLevel(CaptureLevel.All);
Even if you initialized the 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.)

SpringBoot unit test configuration

I created a spring-boot 1.4.0 application and I would like to internationlize it using yaml file.
I created a class for loading the configuration from the yaml file like it is explained in the documentation here http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties.
I would like to create a test to check that my class has correctly loaded the properties from the yaml file.
If we keep the exemple from the documentation how to create a unit test that will load a yaml file (with a different name that application.yml) and check that the method getUsername() will return the value from the yaml file ?
Here is the code I have but still can't load the username :
#Component
#ConfigurationProperties(locations = "classpath:mylocalizedprops.yml", prefix="connection")
public class ConnectionProperties {
private String username;
// ... getters and setters
}
and the test class
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = Application.class)
public class InternationalizationTest {
#Autowired
private ConnectionProperties connectionProperties;
public void propsShouldBeNotNull() {
assertNotNull(connectionProperties);
}
public void userNameShouldBeCorrect() {
assertEquals(connectionProperties.getUsername(), expectedUserName);
}
}
I have failed the userNameShouldBeCorrect test. The file mylocalizedprops.yml is located in the src/main/resources folder of a Maven structured application.
I would consider this an integration test, not a unit-test because you are testing the interaction between various components. Regardless, here is how I would do it.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = YourApplication.class)
public class InternationalizationTests() {
#Autowired
ConnectionProperties connectionProperties;
#Test
public void testCorrectTranslationLoaded() {
Assert.assertEquals("english-username", connectionProperties.getUsername());
}
}
You can also create a test configuration if you would like to, which you can specify which translation to load. You would then need different classes to test different configurations. See the docs: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
Unit test can be done easily with Jmockit
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;
import mockit.Verifications;
class RuleApiApplicationTest {
#Mocked
private ConfigurableApplicationContext mockedContext;
#Test
void testApplicationRun() {
new MockUp<SpringApplication>() {
#Mock
public ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return mockedContext;
}
};
RuleApiApplication.main(new String[]{});
new Verifications() {{
SpringApplication.run(RuleApiApplication.class, new String[]{});
}};
}
}

How to test a function with EntityManager in play framework 2.5

I want to test a code that is "service" level or "dao" level.
but I couldn't resolve a exception
"No EntityManager bound to this thread. Try wrapping this call in
JPAApi.withTransaction, or ensure that the HTTP context is setup on
this thread."
This is a my code for testing by junit.
and the code what make a exception is userService.createUser(); in function "createUser"
#Inject
Application application;
#Before
public void setup() {
Module testModule = new AbstractModule() {
#Override
public void configure() {
}
};
GuiceApplicationBuilder builder = new GuiceApplicationLoader()
.builder(new ApplicationLoader.Context(Environment.simple()))
.overrides(testModule);
Guice.createInjector(builder.applicationModule()).injectMembers(this);
Helpers.start(application);
}
#After
public void teardown() {
Helpers.stop(application);
}
#Test
#Transactional
public void createUser() {
running(application, () -> {
UserService userService = application.injector().instanceOf(UserService.class);
userService.createUser();
});
}
Please, Help me to resolve the exception
thx ~
As a thought, you might add another injected field:
#Inject play.db.jpa.JPAApi japApi
Then in your test you can call jpaApi.withTransaction(anotherRunnableBlock);
probably too late for JungGyu Kim, but for other who google this issue.
I found solution for version 2.6.x, but should work also for 2.5.x.
package models;
import org.junit.Before;
import org.junit.Test;
import play.Application;
import play.db.jpa.JPAApi;
import play.test.Helpers;
import play.test.WithApplication;
import java.util.stream.Stream;
import static org.junit.Assert.assertTrue;
public class MyRepositoryTest extends WithApplication {
#Override
public Application provideApplication() {
return Helpers.fakeApplication(Helpers.inMemoryDatabase());
}
JPAApi jpaApi;
MyRepository myRepository;
#Before
public void init() {
// must get instances like this, as application is created for each test
jpaApi = app.injector().instanceOf(JPAApi.class);
userRepository = app.injector().instanceOf(UserRepository.class);
// no need to setup / clear DB, WithApplication create new DB for each test
}
#Test
public void testGetAllEntries() {
// insert some data first
performNativeQuery("INSERT INTO ...");
// call tested method
final Stream<Entity> result = myRepository.getAllEntries();
// perform some assertions
assertTrue(result.count() == 1);
}
private void performNativeQuery(final String query) {
jpaApi.withTransaction(em -> em.createNativeQuery(query).executeUpdate());
}
}

How to set up already consistent data for Google App Engine unit tests?

I know that App Engine datastore queries are only eventually consistent. However, for some of my tests, I would like to seed the datastore with already consistent data (i.e. it was saved a long time before the test occurred and is now globally consistent).
How can I make sure that the initial data is consistent before running the tests? I would like to still be able to require that actions under test do not require immediate consistency.
I'm using Google Cloud Endpoints for Java, but I'm not anything specific to Endpoints here.
I ended up creating the following BaseTest class and having all of my tests inherit from that:
package com.example;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.dev.HighRepJobPolicy;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
public class BaseTest {
public static final class Policy implements HighRepJobPolicy {
static boolean shouldApply = false;
public static void applyAll() {
shouldApply = true;
}
public static void applyNone() {
shouldApply = false;
}
#Override
public boolean shouldApplyNewJob(Key entityGroup) {
return shouldApply;
}
#Override
public boolean shouldRollForwardExistingJob(Key entityGroup) {
return shouldApply;
}
}
public final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
.setAlternateHighRepJobPolicyClass(Policy.class));
#Before
public void setUp() {
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
}
Then tests can be of the form:
#Test
public void thingShouldDoX() throws Exception {
Policy.applyAll();
// Do setup here, everything inside will be consistent.
Policy.applyNone();
// Run code under test here, without consistency.
}

Spring MVC Integration Test with Selenium

I want to do an integration test on my SpringMVC application using Selenium, with something like:
#Test
public void mytest() {
WebDriver driver = new FirefoxDriver();
driver.get("localhost:8080/myapp/mycontroller");
List<WebElement> elements = driver.findElements(By.cssSelector(".oi"));
assertThat(elements, hasSize(1));
}
Is it possible to "run" my app, the same way that my mvn tomcat7:run would do, and then perform my selenium tests?
Update:
I'm using Spring 4.0.x. I already have Unit Tests for every classes on my webapp, but I need an Integration Test. My controllers are already being tested with MockMVC and spring-test-framework... but I would like to do a selenium integration test.
After a lot o tries, i ended up with a base class for my Selenium Integration tests:
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.openqa.selenium.firefox.FirefoxDriver;
import static io.github.seleniumquery.SeleniumQuery.$;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
public class SeleniumAcceptanceTest {
private static final String WEBAPP_FOLDER = "../../src/main/webapp";
private static final String APP_CONTEXT = "/myapp";
private static final int ANY_RANDOM_PORT_AVAIABLE = 0;
static Server server;
protected static String urlBase;
#BeforeClass
public static void prepareTests() throws Exception {
startWebAppServer();
$.browser.setDefaultDriver(new FirefoxDriver());
}
#AfterClass
public static void finalizaTests() {
$.browser.quitDefaultBrowser();
}
private static void levantarServidorDeAplicacao() throws Exception {
server = new Server(QUALQUER_PORTA_DISPONIVEL);
String rootPath = SeleniumAcceptanceTest.class.getClassLoader().getResource(".").toString();
WebAppContext webapp = new WebAppContext(rootPath + WEBAPP_FOLDER , "");
webapp.setContextPath(APP_CONTEXT );
server.setHandler(webapp);
server.start();
while (true) {
if (server != null && server.isStarted()) {
break;
}
}
int port = server.getConnectors()[0].getLocalPort();
urlBase = "http://localhost:" + port + APP_CONTEXT ;
}
}
And then, a test class extends this class:
public class AlertasAcceptanceTest extends SeleniumAcceptanceTest {
#Test
public void alertas_index__must_show_table_with_4_lines() {
//given
doLogin();
//when
$.browser.openUrl(urlBase + "/alertas/" );
int linesInTheTable = $("table tr").size();
//then
assertThat(linesInTheTable , is(4));
}
}
I hate answering a question with a question, but... 1) do you have to use Selenium or could it be a jUnit test? 2) which version of Spring MVC do you use? Spring 3.2 added a VERY neat feature that lets you spin up mock MVC and execute HTTP requests against it. This way you don't have to worry about starting/stopping your server and all your tests are done from "within" the app itself. Here is a snippet:
#Test
public void addAsUser() throws Exception {
TodoDTO added = TodoTestUtil.createDTO(null, "description", "title");
mockMvc.perform(post("/api/todo")
.contentType(IntegrationTestUtil.APPLICATION_JSON_UTF8)
.content(IntegrationTestUtil.convertObjectToJsonBytes(added))
.with(userDetailsService("user"))
)
.andExpect(status().isOk())
.andExpect(content().contentType(IntegrationTestUtil.APPLICATION_JSON_UTF8))
.andExpect(content().string("{\"id\":3,\"description\":\"description\",\"title\":\"title\"}"));
}
Full article can be found here.

Categories