Java 使用Selenium WebDriver和TestNG处理单点登录

Java 使用Selenium WebDriver和TestNG处理单点登录,java,selenium,selenium-webdriver,testng,single-sign-on,Java,Selenium,Selenium Webdriver,Testng,Single Sign On,条件: public abstract class Validation { // other variables public static WebDriver driver = new FirefoxDriver(); public void doLogin() throws Exception { // something } public void validateDocuments(String portal, String

条件:

public abstract class Validation {
    // other variables
    public static WebDriver driver = new FirefoxDriver();

    public void doLogin() throws Exception {
        // something
    }

    public void validateDocuments(String portal, String navigation,
            String category, String title, String fileName) throws Exception {
        // driver is used here      
    }
}

public class AMSValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/ams/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForAMS() throws Exception {
        // return test data for ams
    }

    @Test(dataProvider = "getDataForAMS")
    public void validateAMS(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}

public class SAPValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/sap/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForSAP() throws Exception {
        // return test data for sap
    }

    @Test(dataProvider = "getDataForSAP")
    public void validateSAP(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Validation Suite" verbose="2">
    <test name="AMS Test">
        <parameter name="baseUrl" value="https://website.com/ams/" />
        <classes>
            <class name="com.website.tests.AMSValidation" />
        </classes>
    </test>

    <test name="SAP Test">
        <parameter name="baseUrl" value="https://website.com/sap/" />
        <classes>
            <class name="com.website.tests.SAPValidation" />
        </classes>
    </test>
</suite>
PASSED: validateAMS("portal", "navigation", "category", "title", "filename")

===============================================
    AMS Test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

FAILED CONFIGURATION: @BeforeTest setUp("https://website.com/sap/")
org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
// rest of stack trace

SKIPPED: validateSAP("portal", "navigation", "category", "title", "filename")

===============================================
    SAP Test
    Tests run: 1, Failures: 0, Skips: 1
    Configuration Failures: 1, Skips: 0
===============================================


===============================================
Validation Suite
Total tests run: 2, Failures: 0, Skips: 1
Configuration Failures: 1, Skips: 0
===============================================
  • 每个测试类的不同基本URL
  • 每个基本url具有相同的登录凭据(sso)
  • 每个测试类的不同数据集
问题:
它通过了
AMSValidation
,但跳过了
SAPValidation
。它的意思是调用quit()后不能使用FirefoxDriver。 但是在运行每个类的测试时,它们通过了。

代码:

public abstract class Validation {
    // other variables
    public static WebDriver driver = new FirefoxDriver();

    public void doLogin() throws Exception {
        // something
    }

    public void validateDocuments(String portal, String navigation,
            String category, String title, String fileName) throws Exception {
        // driver is used here      
    }
}

public class AMSValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/ams/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForAMS() throws Exception {
        // return test data for ams
    }

    @Test(dataProvider = "getDataForAMS")
    public void validateAMS(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}

public class SAPValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/sap/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForSAP() throws Exception {
        // return test data for sap
    }

    @Test(dataProvider = "getDataForSAP")
    public void validateSAP(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Validation Suite" verbose="2">
    <test name="AMS Test">
        <parameter name="baseUrl" value="https://website.com/ams/" />
        <classes>
            <class name="com.website.tests.AMSValidation" />
        </classes>
    </test>

    <test name="SAP Test">
        <parameter name="baseUrl" value="https://website.com/sap/" />
        <classes>
            <class name="com.website.tests.SAPValidation" />
        </classes>
    </test>
</suite>
PASSED: validateAMS("portal", "navigation", "category", "title", "filename")

===============================================
    AMS Test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

FAILED CONFIGURATION: @BeforeTest setUp("https://website.com/sap/")
org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
// rest of stack trace

SKIPPED: validateSAP("portal", "navigation", "category", "title", "filename")

===============================================
    SAP Test
    Tests run: 1, Failures: 0, Skips: 1
    Configuration Failures: 1, Skips: 0
===============================================


===============================================
Validation Suite
Total tests run: 2, Failures: 0, Skips: 1
Configuration Failures: 1, Skips: 0
===============================================
testng.xml:

public abstract class Validation {
    // other variables
    public static WebDriver driver = new FirefoxDriver();

    public void doLogin() throws Exception {
        // something
    }

    public void validateDocuments(String portal, String navigation,
            String category, String title, String fileName) throws Exception {
        // driver is used here      
    }
}

public class AMSValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/ams/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForAMS() throws Exception {
        // return test data for ams
    }

    @Test(dataProvider = "getDataForAMS")
    public void validateAMS(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}

public class SAPValidation extends Validation {

    @Parameters("baseUrl")
    @BeforeTest(alwaysRun = true)
    public void setUp(@Optional("https://website.com/sap/") String baseUrl)
            throws Exception {

        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.get(baseUrl);
        doLogin();
    }

    @DataProvider
    public Object[][] getDataForSAP() throws Exception {
        // return test data for sap
    }

    @Test(dataProvider = "getDataForSAP")
    public void validateSAP(String portal, String navigation, String category,
            String title, String fileName) throws Exception {
        validateDocuments(portal, navigation, category, title, fileName);
    }

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        driver.quit();
    }
}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Validation Suite" verbose="2">
    <test name="AMS Test">
        <parameter name="baseUrl" value="https://website.com/ams/" />
        <classes>
            <class name="com.website.tests.AMSValidation" />
        </classes>
    </test>

    <test name="SAP Test">
        <parameter name="baseUrl" value="https://website.com/sap/" />
        <classes>
            <class name="com.website.tests.SAPValidation" />
        </classes>
    </test>
</suite>
PASSED: validateAMS("portal", "navigation", "category", "title", "filename")

===============================================
    AMS Test
    Tests run: 1, Failures: 0, Skips: 0
===============================================

FAILED CONFIGURATION: @BeforeTest setUp("https://website.com/sap/")
org.openqa.selenium.remote.SessionNotFoundException: The FirefoxDriver cannot be used after quit() was called.
// rest of stack trace

SKIPPED: validateSAP("portal", "navigation", "category", "title", "filename")

===============================================
    SAP Test
    Tests run: 1, Failures: 0, Skips: 1
    Configuration Failures: 1, Skips: 0
===============================================


===============================================
Validation Suite
Total tests run: 2, Failures: 0, Skips: 1
Configuration Failures: 1, Skips: 0
===============================================

在抽象基类验证中,驱动程序实例变量被标记为static,因此所有子对象只有一个实例,一旦从其中一个实例调用quit方法,则其他子实例将无法进一步使用同一驱动程序,因此从声明中删除static,如下所示

public WebDriver driver = new FirefoxDriver();

希望它有帮助

根据我在java方面的知识,类“Validation”已经由我们的一个类AMSValidation加载,这意味着,所有静态成员也会加载。所以当第一次加载类时,它的静态内容也会加载。当这些静态成员被任何其他类修改时,这些内容的更新状态也可用于其他类,因此,当我们从第一个类“AMSValidation”退出驱动程序实例(静态)时,驱动程序将退出,并且不可用于第二个类,即“SAPValidation”,因此我们面临此类异常

为了避免此SessionNotFoundException,最好为“Validations”创建对象,这样它就可以创建两个不同的驱动程序,但从技术上讲,因为我们的Validation类是一个抽象类,不能实例化抽象类对象

方法1:最好创建另一个具体类来验证类,然后从新创建的类扩展子类(AMSValidation和SAPValidation) 方法2:在现有类设计中创建驱动程序时,只需删除“static”关键字


毕竟,Java在使用类加载器时有点棘手,为了节省内存和提高性能

将driver.quit()调用移动到aftersuite()方法。我猜静态webdriver是为了让驱动程序会话在测试期间保持活动状态。如果是,将驱动程序初始化移到beforesuite()方法。

将驱动程序.quit()调用移到aftersuite()方法。我猜静态webdriver是为了让驱动程序会话在测试期间保持活动状态。如果是这样,请将驱动程序初始化移到beforesuite()方法。@Grasshopper您的注释解决了这个问题。“如果你能把它贴出来作为答案,我会很高兴把它标记为接受。”西尔弗贴出来作为答案。