I'm trying to learning Serenity BDD framework but i encounter some issues which need guidance from expect.I have downloaded serenity-cucumber4-starter-master from github.
Problems:
AFAIK, there is Tasks, Screen and Actions classes creation but I did not found it in the project according to this theory.
How is the implementation of this example different from screenplay design patterns?
My Code so far:
public class LoginTask implements Task {
private HomepageScreen hp;
#Override
#Step("Landing on Guru Bank Website")
public <T extends Actor> void performAs(T obj) {
obj.attemptsTo(Open.browserOn(hp));
}
}
#RunWith(SerenityRunner.class)
public class CucumberTestSuite {
#Managed(driver = "chrome")
private WebDriver browser;
private Actor john = Actor.named("john");
// =================================================================================
#Before
public void setup() {
john.can(BrowseTheWeb.with(browser));
}
#Test
public void login() throws InterruptedException {
//givenThat(john).can(BrowseTheWeb.with(browser));
System.out.println("Automate web browser");
//givenThat(john).wasAbleTo(LoginTask.);
Thread.sleep(9000);
}
}
givenThat() method is undefined. Where to get the import location?
Please help. Thanks.
The givenThat() method (and other similar methods) are defined in net.serenitybdd.screenplay.GivenWhenThen.
import static net.serenitybdd.screenplay.GivenWhenThen.seeThat;
Related
Main Block:
public class test3 extends utility {
public WebDriver driver;
#BeforeTest
public void invokeBrowser() throws IOException {
driver = base();
driver.get(resource.getProperty("url"));
}
#Test
public class thirdPage {
public void main() {
actionTest test3 = new actionTest();
test3.executeTest();
}
}
}
Code performing mouse Actions:
public class actionTest {
public void executeTest() {
Actions execute = new Actions();
execute.moveToElement(driver.findElement(By.id("header-search-input"))).click().keyDown(Keys.SHIFT).sendKeys("Cricket").build().perform();
driver.findElement(By.id("header-desktop-search-button")).click();
}
}
Above code results in "NullPointerException" stating driver = null while executing block test3.executeTest();
Restructuring your codebase might help you to fix this issue. Create a base test class. Add the code related to web driver initialization and other main things there. Then create another class for your tests. Inherit it from the base test class. Then you can use the initialized driver in your all test classes.
I'm building new automation infrastructure using tesng, extent-report and cucumber integrated together.
using the following code.
#CucumberOptions(strict= false,
plugin = {"pretty" ,"html:test-output/cucumber",
"com.vimalselvam.cucumber.listener.ExtentCucumberFormatter:",
"json:test-output/cucumber/cucumber.json", "pretty:test-output/cucumber/cucumber-pretty.txt",
"usage:test-output/cucumber/cucumber-usage.json", "junit:test-output/cucumber/cucumber-results.xml"
,"com.cucumber.listener.ExtentCucumberFormatter:test-output/cucumber/cucumber-extent-reports/report.html"}
// , glue = {"#User"}
, monochrome = true)
public abstract class SROTestInfra extends AbstractTestNGCucumberTests{
PageFactory pageFactory = new PageFactory();
protected WebDriver driver;
}
I'm trying to report instance in order to add an Info messages, but reprot access control is only for package as shown in this open source code.
public class ExtentCucumberFormatter implements Reporter, Formatter {
/* some code
****************
****************
*/
private static void setExtentHtmlReport(ExtentHtmlReporter htmlReport) {
htmlReporterThreadLocal.set(htmlReport);
}
static ExtentHtmlReporter getExtentHtmlReport() {
return htmlReporterThreadLocal.get();
}
private static void setExtentReport(ExtentReports extentReports) {
reportsThreadLocal.set(extentReports);
}
static ExtentReports getExtentReport() {
return reportsThreadLocal.get();
}
}
any help please.
You can get the reporter instance through com.vimalselvam.cucumber.listener.Reporter class. For more information, refer this: https://github.com/email2vimalraj/CucumberExtentReporter/blob/master/src/main/java/com/vimalselvam/cucumber/listener/Reporter.java#L29
Overview: There are instances where in I want to stop the running cucumber test pack midway -- say for example when x number of tests failed.
I can do this just fine but I want the json file (plugin = {json:...}) to be generated when the test stops. Is this doable?
What I've tried so far:
Debug and see where the reporting / plugin generation happens. It seems to be when this line executes:
Cucumber.java: runtime.getEventBus().send.....
#Override
protected Statement childrenInvoker(RunNotifier notifier) {
final Statement features = super.childrenInvoker(notifier);
return new Statement() {
#Override
public void evaluate() throws Throwable {
features.evaluate();
runtime.getEventBus().send(new TestRunFinished(runtime.getEventBus().getTime()));
runtime.printSummary();
}
};
}
I was hoping to access the runtime field but it has a private modifier. I also tried accessing it via reflections but I'm not exactly getting what I need.
Found a quite dirty, but working solution and got what I need. Posting my solution here in case anyone might need.
Create a custom cucumber runner implementation to take the runtime instance.
public final class Foo extends Cucumber {
static Runtime runtime;
/**
* Constructor called by JUnit.
*
* #param clazz the class with the #RunWith annotation.
* #throws IOException if there is a problem
* #throws InitializationError if there is another problem
*/
public Foo(Class clazz) throws InitializationError, IOException {
super(clazz);
}
#Override
protected Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader, RuntimeOptions runtimeOptions) throws InitializationError, IOException {
runtime = super.createRuntime(resourceLoader, classLoader, runtimeOptions);
return runtime;
}
}
Call the same line that generates the file depending on the plugin used:
public final class ParentHook {
#Before
public void beforeScenario(Scenario myScenario) {
}
#After
public void afterScenario() {
if (your condition to stop the test) {
//custom handle to stop the test
myHandler.pleaseStop();
Foo.runtime.getEventBus().send(new TestRunFinished(Foo.runtime.getEventBus().getTime()));
}
}
}
This will however require you to run your test via Foo.class eg:
#RunWith(Foo.class) instead of #RunWith(Cucumber.class)
Not so much value here but it fits what I need at the moment. I hope Cucumber provides a way to do this out of the box. If there's a better way, please do post it here so I can accept your answer once verified.
Why not quit?
import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.When;
public class StepDefinitions {
private static int failureCount = 0;
private int threshold = 20;
#When("^something$")
public void do_something() {
// something
}
#After
public void after(Scenario s) {
if (s.isFailed()) ++failureCount;
}
#Before
public void before() {
if (failureCount > threshold) {
if (driver !=null) {
driver.quit();
driver = null;
}
}
}
I am trying to write a test suite using JUnit4 by relying on JUnit4TestAdapter. Having a look at the code of this class I saw that it only works with a Class as input. I would like to build a test class and set a parameter on it before running it with my TestSuite. Unfortunately, Junit4TestAdapter is building the test by using reflection (not 100% sure about the mechanism behind it), which means that I cannot change my test class on runtime.
Has anybody done anything similar before? Is there any possible workaround to this issue? Thanks for your help!
public class SimpleTest {
#Test
public void testBasic() {
TemplateTester tester = new TemplateTester();
ActionIconsTest test = new ActionIconsTest();
test.setParameter("New Param Value");
tester.addTests(test);
tester.run();
}
}
/////
public class TemplateTester {
private TestSuite suite;
public TemplateTester() {
suite = new TestSuite();
}
public void addTests(TemplateTest... tests) {
for (TemplateTest test : tests) {
suite.addTest(new JUnit4TestAdapter(test.getClass()));
}
}
public void run() {
suite.run(new TestResult());
}
}
/////
public interface TemplateTest {
}
/////
public class ActionIconsTest extends BaseTestStrategy implements TemplateTest {
#Test
public void icons() {
//Test logic here
}
public void navigateToTestPage() {
//Here I need the parameter
}
}
/////
public abstract class BaseTestStrategy {
protected String parameter;
#Before
public void init() {
navigateToTestPage();
}
public abstract void navigateToTestPage();
public void setParameter(String parameter) {
this.parameter = parameter;
}
}
I am trying to test a web application with Selenium. The way I want to test is by splitting the functionality, e.g., I want to test the available icons (ActionIconsTest), then I'd like to test other parts like buttons, etc.
The idea behind this is to have a better categorization of the functionality available in certain screen. This is quite coupled with the way we are currently developing our web app.
With this in mind, TemplateTest is just an interface implemented by the different kind of tests (ActionIconTest, ButtonTest, etc) available in my system.
TemplateTester is a Junit suite test with all the different tests that implement the interface TemplateTest.
The reason for this question is because I was trying to implement a Strategy pattern and then realized of the inconvenient of passing a class to Junit4TestAdapter in runtime.
Well, taking in account that JUNIT needs your tester's Class object as an object factory (so he can create several instances of your tester), I can only suggest you pass parameters to your tester through System Properties.
Moreover, it's the recommended way of passing parameters: http://junit.org/faq.html#running_7
After a whole night spent in test (without any luck) I need some support with my interface.
I'm working directly on the Android frameworks and I created a class that works as a Binder with a WeakHashMap to control the callbacks.
Here is the code:
MyCallback:
public interface MyCallback {
public void fire();
}
MyBinder:
public static WeakHashMap<String, MyCallback> mCallbacks =
new WeakHashMap<String, MyCallback>();
public static void setup(MyCallback callback) {
if(mCallbacks.get(callback.getClass().getName()) == null) {
mCallbacks.put(callback.getClass().getName(), callback);
}
}
public static void letsgo() {
Log.d("size", " " + mCallbacks.size()); // IMPORTANT
for (MyCallback cb : mCallbacks.values()) {
cb.fire();
}
}
These 2 classes are written into frameworks so I created 2 test applications with a simple class that implements my interface:
public class FirstApp implements MyCallback {
public FirstApp() {
MyBinder.setup(this);
}
#Override
public void fire() {
Log.d("app1", "fired");
}
}
public class SecondApp implements MyCallback {
public SecondApp() {
MyBinder.setup(this);
}
#Override
public void fire() {
Log.d("app2", "fired");
}
}
Ok at this point I made another class (all these 3 classes, so the 2 that implements the interface and the following one are written into different packages)
In this third class i just call: MyBinder.letsgo();
The issue I'm facing, and that I'm trying to solve since... 8/9 hours is that: If i run letsgo() on the third pack the logs shown 0 for the callbacks WeakHashMap size. if i run letsgo() on the second package it works but it only fires the callback in the same package. the same if i run it on the first package.
I tried also with HashMap instead of WeakHashMap since i red that objects must be referenced but without any luck. I wonder if someone can help me and let me go sleep :D Thanks!