У меня есть два разных класса шагов, которые имеют общий жизненный цикл до и после шагов.Поэтому я создал общий класс шагов, в котором код инициализации и очистки веб-драйвера используется в качестве жизненного цикла до и после методов.Этот общий класс расширяется обоими классами определения шага.При запуске этих историй я вижу исключение нулевого указателя при доступе к веб-драйверу в классе второго шага.Дальнейшая отладка Я заметил, что общие шаги вызываются с использованием объекта класса первого шага для каждого сценария в файле истории.
My Story File 1.
Meta:
@author prasanta biswas
@theme UI Test
Narrative:
As a Facebook User
In order to update my status
I want to login to my Facebook account
So that I can update my status message
Lifecycle:
Before:
Scope: SCENARIO
Given I initialize my chrome browser instance
After:
Scope: SCENARIO|STORY
Outcome: ANY
Given I cleanup my browser instance
Scenario: Update Facebook status message
Meta:
@type positive
@data valid
@app facebook
Given I have a Facebook account
And I open Facebook in my web browser with the <url>
And I login to Facebook with <username> and <password>
Then I check if status message box is present in the homepage after successful login
When I put my status <message> in the status box
And I click post button
Then I should see my new status <message> in my news feeds
Examples:
|username|password|url|message|
|VALID_USERNAME|VALID_PASSWORD|https://www.facebook.com|Hi Facebook|
My Story File2.
Meta:
@author prasanta biswas
@theme UI Test
Narrative:
As a wallethub user
I want to review a particual insurance policy
So that the review appears in my review list
Lifecycle:
Before:
Scope: SCENARIO
Given I initialize my chrome browser instance
After:
Scope: SCENARIO|STORY
Outcome: ANY
Given I cleanup my browser instance
Scenario: Create review for a particual walletHub insurance policy
Meta:
@type positive
@data valid
@app wallethub
Given I have a WalletHub test account
And I open wallethub in the web browser using <url>
And I login to my wallethub account with <email> and <password>
Then I should see my <username> on my homepage
Given I navigate to <reviewUrl> after login
And I count the current review count in my review list
And I navigate to <insuranceCompanyUrl>
When I click Write a Review button
Then I should see new review page
Given I select insurance <policy> from insurance list in new review page
And I apply rating <star>
And I put my review <text>
When I click submit button
Then I should see confirmation <message>
And I should see a my new review <text> in my <reviewUrl>
Examples:
|email|password|url|username|reviewUrl|insuranceCompanyUrl|policy|text|star|message|
|eaxmple@gmail.com|asssdd|https://wallethub.com/|pthewizard|https://wallethub.com/profile/pthewizard/reviews/|http://wallethub.com/profile/test_insurance_company/|Health|This is my first reviewHealthPolicy.|5|Awesome!|
Класс CommonStep:
package io.jbehavetutorials.steps.common;
import io.jbehavetutorials.testutility.BrowserFactory;
import org.jbehave.core.annotations.Given;
import org.jbehave.core.annotations.Named;
import org.openqa.selenium.WebDriver;
/**
* Created by prasantabiswas on 23/05/18.
*/
public class CommonSteps {
protected WebDriver webDriver;
@Given("I initialize my $browserName browser instance")
public void setUpMethod(@Named("browserName") String browser)
{
webDriver = BrowserFactory.getDriver(browser);
}
@Given("I cleanup my browser instance")
public void tearDownMethod()
{
// Cleanup
if(webDriver != null)
webDriver.quit();
}
}
Мой класс определения первого шага:
package io.jbehavetutorials.steps.facebook;
import io.jbehavetutorials.appmodule.facebook.FacebookApp;
import io.jbehavetutorials.constants.Browser;
import io.jbehavetutorials.steps.common.CommonSteps;
import io.jbehavetutorials.testutility.BrowserFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jbehave.core.annotations.*;
import org.junit.Assert;
import org.openqa.selenium.WebDriver;
import java.net.MalformedURLException;
/**
* Created by prasantabiswas on 21/05/18.
*/
public class FacebookStatusPost extends CommonSteps{
FacebookApp facebookApp;
Logger logger = LogManager.getLogger(FacebookStatusPost.class);
@Given("I have a Facebook account")
@Pending
public void iHaveAFacebookAccount()
{
try {
facebookApp = new FacebookApp(webDriver); // Working perfectly here
Assert.assertTrue("Facebook object creation failed",facebookApp!=null);
}
catch (Exception e)
{
logger.error("Error",e);
}
}
}
Мой класс определения второго шага:
package io.jbehavetutorials.steps.wallethub;
import io.jbehavetutorials.appmodule.wallethub.WalletHubApp;
import io.jbehavetutorials.constants.Browser;
import io.jbehavetutorials.steps.common.CommonSteps;
import io.jbehavetutorials.testutility.BrowserFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jbehave.core.annotations.*;
import org.junit.Assert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.net.MalformedURLException;
/**
* Created by prasantabiswas on 21/05/18.
*/
public class WalletHubReviewInsurance extends CommonSteps {
WalletHubApp wallethubApp;
int reviewCount = 0;
Logger logger = LogManager.getLogger(WalletHubReviewInsurance.class);
@Given("I have a WalletHub test account")
public void iHaveAWallerHubTestAccount()
{
try{
wallethubApp = new WalletHubApp(webDriver);//Getting null pointer here
}
catch (Exception e)
{
logger.error("Error",e);
}
}
}
Класс карты истории:
package io.jbehavetutorials;
import io.jbehavetutorials.steps.facebook.FacebookStatusPost;
import io.jbehavetutorials.steps.wallethub.WalletHubReviewInsurance;
import io.jbehavetutorials.steps.weatherapi.WeatherAPITest;
import org.jbehave.core.embedder.StoryControls;
import org.jbehave.core.junit.JUnitStories;
import java.text.SimpleDateFormat;
import java.util.List;
import org.jbehave.core.Embeddable;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.model.ExamplesTableFactory;
import org.jbehave.core.model.TableTransformers;
import org.jbehave.core.parsers.RegexStoryParser;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.reporters.SurefireReporter;
import org.jbehave.core.steps.*;
import org.jbehave.core.steps.ParameterConverters.DateConverter;
import org.jbehave.core.steps.ParameterConverters.ExamplesTableConverter;
import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
import static org.jbehave.core.reporters.Format.CONSOLE;
import static org.jbehave.core.reporters.Format.HTML;
import static org.jbehave.core.reporters.Format.TXT;
import static org.jbehave.core.reporters.Format.XML;
/**
* <p>
* {@link Embeddable} class to run multiple textual stories via JUnit.
* </p>
* <p>
* Stories are specified in classpath and correspondingly the {@link LoadFromClasspath} story loader is configured.
* </p>
*/
public class StoryMap extends JUnitStories {
public StoryMap() {
configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true)
.doIgnoreFailureInView(true).useThreads(1);
// configuredEmbedder().useMetaFilters(Arrays.asList("+type negative"));
}
@Override
public Configuration configuration() {
Class<? extends Embeddable> embeddableClass = this.getClass();
// Start from default ParameterConverters instance
ParameterConverters parameterConverters = new ParameterConverters();
// Start from default ParameterControls instance
ParameterControls parameterControls = new ParameterControls();
// factory to allow parameter conversion and loading from external resources (used by StoryParser too)
ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(new LocalizedKeywords(), new LoadFromClasspath(embeddableClass),parameterConverters,parameterControls, new TableTransformers());
// add custom converters
parameterConverters.addConverters(new DateConverter(new SimpleDateFormat("yyyy-MM-dd")),
new ExamplesTableConverter(examplesTableFactory));
return new MostUsefulConfiguration()
//.usePendingStepStrategy(new FailingUponPendingStep())
.useStoryControls(new StoryControls().doDryRun(false))
.useStoryLoader(new LoadFromClasspath(embeddableClass))
.useStoryParser(new RegexStoryParser(examplesTableFactory))
// .useStoryParser(new GherkinStoryParser())
.useStoryReporterBuilder(new StoryReporterBuilder()
.withSurefireReporter(new SurefireReporter(embeddableClass))
.withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
.withDefaultFormats()
.withFormats(CONSOLE, TXT, HTML, XML)
.withFailureTrace(true)
.withFailureTraceCompression(true))
.useParameterConverters(parameterConverters)
.useParameterControls(parameterControls);
}
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new FacebookStatusPost(), new WalletHubReviewInsurance(), new WeatherAPITest());
// return new ScanningStepsFactory(configuration(),"io.jbehavetutorials.steps"); //requires reflection dependency
}
@Override
protected List<String> storyPaths() {
return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "**/*.story", "**/excluded*.story");
}
}
Есть ли способ вызвать эти общие методы жизненного цикла отдельно от разных объектов класса определения шага, чтобы отдельный экземпляр веб-драйвера создавался для разных классов определения шага.