无法在JBehave中具有共同生命周期步骤的不同故事之间共享Web驱动程序实例

时间:2018-05-23 16:47:24

标签: java jbehave

我有两个不同的步骤类,它们在步骤之前和之后都有共同的生命周期。所以我创建了一个通用的步骤类,它将webdriver初始化和清理代码作为方法之前和之后的生命周期。这个公共类由步骤定义类扩展。运行这些故事时,我在第二步课程中访问Web驱动程序时看到空指针异常。进一步调试我注意到,每次故事文件中都有一个场景时,使用第一步类对象调用常用步骤。

我的故事档案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|

我的故事档案2。

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");

    }

}

有没有办法从不同的步骤定义类对象中分别调用这些公共生命周期方法,以便为不同的步骤定义类创建单独的webdriver实例。

1 个答案:

答案 0 :(得分:0)

解决方法是在static类中创建驱动程序实例CommonSteps。这不是一个具体的解决方案,因为它不能与同时运行故事的多个线程一起使用,因为它会使驱动程序实例容易受到攻击。