Java+Selenium+TestNG+Allure

内容分享2周前发布
0 0 0

Java+Selenium+TestNG+Allure

一、创建maven项目二、安装selenium1、引入selenium2、引入WebDriver2.1 手动引入2.2 自动下载2.3 完整代码

三、引入依赖四、编写自动化脚本五、元素的定位5.1、通过id查找元素5.2、通过class查找元素5.3、通过name查找元素5.4、通过cssSelector来查找元素5.5、通过XPATH来查找元素
六、常用测试方法6.1 操作元素6.2 获取内容6.3 页面请求6.4 窗口6.4.1 获取百度首页句柄以及新闻页面句柄6.4.2 切换句柄6.4.3 设置窗口大小
6.5 等待6.5.1 强制等待6.5.2 隐式等待6.5.3 显式等待
6.6 弹窗6.7 文件上传6.7.1文件操作工具类示例
6.8 关闭和退出6.9 代理配置工具类示例6.10 随机用户代理工具类示例6.11 截图并保存为文件

一、创建maven项目

Java+Selenium+TestNG+Allure

二、安装selenium

1、引入selenium

通过下载jar包,或者通过maven引入。

这里使用 maven 管理项目依赖,所以在pom.xml添加以下依赖:


<!-- Selenium WebDriver Java -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.0</version>
</dependency>

2、引入WebDriver

想用selenium驱动不同的浏览器需要不同的浏览器驱动,这里将会使用Chrome浏览器进行自动化测试,所以需要下载 ChromeDriver ,需要下载与目标浏览器相匹配的版本号的驱动器(不过Chrome浏览器一般都会自动更新,所以直接下载最新版的驱动器就是了)。

2.1 手动引入

手动下载地址: https://chromedriver.chromium.org/downloads
历史版本 Chrome:https://www.slimjet.com/chrome/google-chrome-old-version.php
Java+Selenium+TestNG+Allure


logger.info("使用已下载的 ChromeDriver");
try {
	// 设置系统属性,指定chromedriver的路径
    // 从配置文件中读取 ChromeDriver 路径
    String driverPath = ConfigUtils.getString("webdriver.chrome");
    logger.info("ChromeDriver 路径设置为: {}" , driverPath);
    System.setProperty("webdriver.chrome.driver", driverPath);

} catch (Exception e) {
    logger.error("设置 ChromeDriver 路径失败: {}" , e.getMessage());
    throw new RuntimeException("设置 ChromeDriver 路径失败: " + e.getMessage());
}

2.2 自动下载

webdriver驱动管理依赖,只要引入依赖.就不要我们手动的去处理浏览器版本的问题。
只需要我们在pom.xml文件中引入依赖,每次使用都会帮助我们下载新的驱动


<!-- webdrivermanager 依赖 自动检测本地浏览器版本,并从官方源下载匹配的驱动程序,无需人工干预 -->
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
    <version>5.8.0</version>
</dependency>

logger.info("自动下载 ChromeDriver");
WebDriverManager.chromedriver().setup();

2.3 完整代码


logger.info("初始化driver");

// 判断是否启动自动下载
if (ConfigUtils.getBoolean("webdriver.autodriver")) {
    logger.info("自动下载 ChromeDriver");
    WebDriverManager.chromedriver().setup();
} else {
    logger.info("使用已下载的 ChromeDriver");
    try {
        // 从配置文件中读取 ChromeDriver 路径
        String driverPath = ConfigUtils.getString("webdriver.chrome");
        logger.info("ChromeDriver 路径设置为: {}" , driverPath);
        System.setProperty("webdriver.chrome.driver", driverPath);

    } catch (Exception e) {
        logger.error("设置 ChromeDriver 路径失败: {}" , e.getMessage());
        throw new RuntimeException("设置 ChromeDriver 路径失败: " + e.getMessage());
    }
}

三、引入依赖


	<properties>
		<!-- 依赖版本 -->
        <selenium.version>3.141.0</selenium.version>
        <webdrivermanager.version>5.8.0</webdrivermanager.version>
        <testng.version>7.8.0</testng.version>
        <allure.version>2.13.2</allure.version>
        <aspectj.version>1.9.20</aspectj.version>
        <slf4j.version>2.0.9</slf4j.version>
        <jetbrains-annotations.version>24.0.1</jetbrains-annotations.version>

        <!-- 插件版本 -->
        <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
        <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
        <allure-maven.version>2.10.0</allure-maven.version>
        <maven-assembly-plugin.version>3.6.0</maven-assembly-plugin.version>

    </properties>
<dependencies>
        <!-- Selenium WebDriver Java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>

        <!-- webdrivermanager 依赖
        自动检测本地浏览器版本,并从官方源下载匹配的驱动程序,无需人工干预
            用途: 自动管理 WebDriver 的二进制文件,简化驱动配置过程。
            使用方式:
                在初始化 WebDriver 前调用 WebDriverManager.chromedriver().setup(); 等方法自动设置驱动。
        -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>${webdrivermanager.version}</version>
        </dependency>
        
        <!-- TestNG 测试框架-->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
			<scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.testng</groupId>
                    <artifactId>testng-old</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Allure TestNG 集成 -->
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-testng</artifactId>
            <version>${allure.version}</version>
			<scope>test</scope>
        </dependency>

        <!-- AspectJ Weaver 供面向切面编程(AOP)的能力,常用于 Allure 测试报告生成。 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <!-- JetBrains Annotations 提供静态分析注解,帮助提高代码质量 -->
        <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>${jetbrains-annotations.version}</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <!-- Allure Maven 报告插件 -->
            <plugin>
                <groupId>io.qameta.allure</groupId>
                <artifactId>allure-maven</artifactId>
                <version>${allure-maven.version}</version>
                <configuration>
                    <reportVersion>${allure.version}</reportVersion>
                </configuration>
            </plugin>
			<!-- Surefire 插件:执行 TestNG 测试 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven-surefire-plugin.version}</version>
                <configuration>
                    <!-- 测试失败后,是否忽略并继续测试 -->
                    <testFailureIgnore>false</testFailureIgnore>
                    <!--设置参数命令行 -->
                    <argLine>
                        <!-- 用于解决TestNG Result中文乱码 -->
                        -Dfile.encoding=UTF-8
                        <!-- 配置拦截器 -->
                        -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    </argLine>
                    <useSystemClassLoader>true</useSystemClassLoader> <!-- 使用系统类加载器 -->
                    <useManifestOnlyJar>false</useManifestOnlyJar> <!-- 禁用 ManifestOnlyJar -->
                    <systemProperties>
                        <property>
                            <!-- 配置 allure 结果存储路径 -->
                            <name>allure.results.directory</name>
                            <value>./allure-results</value>
                        </property>
                    </systemProperties>
                </configuration>

                <dependencies>
                    <!-- allure相关依赖 -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjweaver</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
       </plugins>
     </build>

四、编写自动化脚本

对于代码的测试我们一般都是在test目录下创建,也可以在main方法中创建,但是一般规范都是让我们在test中创建,FirstTest用来编写我们的自动化脚本,run是执行我们的脚本


public void test(){
        //自动下载与当前系统和浏览器版本匹配的驱动程序
        WebDriverManager.chromedriver().setup();
        //访问限制处理
        ChromeOptions options=new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        //生成一个浏览器对象
        WebDriver driver=new ChromeDriver(options);
        driver.get("https://www.baidu.com/");
        driver.findElement(By.cssSelector("#kw")).sendKeys("鞠婧祎");
        driver.findElement(By.cssSelector("#su")).click();
        driver.quit();
    }

当我们完成一次操作之后要关闭driver对象.[driver.quit();]

Java+Selenium+TestNG+Allure
这样我们就完成了一次简单的简单的测试用例

五、元素的定位

一般定位一个元素我们一般使用cssSelector和Xpath.
Java+Selenium+TestNG+Allure
获取web元素按照上述操作定位元素位置之后,右键可以复制 Selector和Xpath
Java+Selenium+TestNG+Allure

5.1、通过id查找元素


// 通过id找到输入框
WebElement inputElement = driver.findElement(By.id("kw"));

5.2、通过class查找元素


WebElement inputElement = driver.findElement(By.className("s_ipt"));

5.3、通过name查找元素


WebElement inputElement = driver.findElement(By.name("wd"));

5.4、通过cssSelector来查找元素


 //找到搜索框之后,输入搜索关键字鞠婧祎
 driver.findElement(By.cssSelector("#kw")).sendKeys("鞠婧祎");
 //点击按钮,也就是"百度一下".click(点击操作)
 driver.findElement(By.cssSelector("#su")).click();
 driver.quit();

5.5、通过XPATH来查找元素

XML路径语⾔,不仅可以在XML⽂件中查找信息,还可以在HTML中选取节点
xpath使⽤路径表达式来选择xml⽂档中的节点
xpath语法中:
获取HTML⻚⾯所有的节点
//*
获取HTML⻚⾯指定的节点
//[指定节点]
//ul :获取HTML⻚⾯所有的ul节点
//input:获取HTML⻚⾯所有的input节点
获取⼀个节点中的直接⼦节点
/
//span/input
获取⼀个节点的⽗节点

//input/… 获取input节点的⽗节点
实现节点属性的匹配
[@…]
//*[@id=‘kw’] 匹配HTML⻚⾯中id属性为kw的节点
使⽤指定索引的⽅式获取对应的节点内容
注意:xpath的索引是从1开始的。
百度⾸⻚通过://div/ul/li[3] 定位到第三个百度热搜标签


//使用Xpath定位
    public void test02() {
        createDriver();
        driver.findElement(By.xpath("//*[@id="kw"]")).sendKeys("鞠婧祎");
        driver.findElement(By.xpath("//*[@id="su"]")).click();
        driver.quit();
    }

六、常用测试方法

6.1 操作元素


// 输入文本
void sendKeys(CharSequence... keysToSend);
// 清空文本
void clear();
// 点击元素
void click();
// 提交表单
void submit();
// 模拟鼠标移动到元素并点击
Actions actions = new Actions(driver);
actions.moveToElement(element).click().perform();
// 执行JavaScript代码
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, document.body.scrollHeight)"); // 滚动到底部

6.2 获取内容


// 获取页面html
String getPageSource();
// 获取页面标题
String getTitle();
// 获取此元素(包括子元素)的可见(即未被CSS隐藏)文本
String getText();
// 获取此元素的标签名
String getTagName();
// 获取元素指定属性的值
String getAttribute(String name);
// 获取当前元素,基于样式的计算属性值
String getCssValue(String propertyName);
// 获取元素的尺寸及其在视口中的位置
Rectangle getRect();

 publ
 ic void test04() {
        createDriver();
        String text = driver.findElement(By.cssSelector("#hotsearch-content-wrapper > li:nth-child(1) > a")).getText();
        System.out.println(text);
        driver.quit();
    }

6.3 页面请求


// 请求一个页面,不支持前进和后退切换
driver.get(url);
// 类似get,支持前进和后退切换
driver.navigate().to(url);
// 退到上一个页面,前提是必须前进了一个页面才能回退
driver.navigate().back();
// 指前进到下一个页面,前提是必须后退后才能前进
driver.navigate().forward();
// 刷新当前页面
driver.navigate().refresh();

6.4 窗口

句柄:每个浏览器窗口或标签页都有一个唯一的标识符(字符串形式),称为窗口句柄


// 切换到指定窗口
driver.switchTo().window(windowHandle);
// 切换到指定框架
driver.switchTo().frame(frameNameOrId);
// 切换到父框架
driver.switchTo().parentFrame();
// 切换到默认内容
driver.switchTo().defaultContent();

6.4.1 获取百度首页句柄以及新闻页面句柄


public void test06() {
        createDriver();
        //进入新闻页面
        driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        //获取百度首页句柄
        String curHandle = driver.getWindowHandle();
        System.out.println(curHandle);
        System.out.println("========================");
        //获取所有句柄
        Set<String> windowHandles = driver.getWindowHandles();
        for (String handle:windowHandles){
            System.out.println(handle);
        }
        driver.quit();
    }

Java+Selenium+TestNG+Allure

6.4.2 切换句柄

当前driver对象指向的是百度首页的句柄,我们要使用新闻页的元素,就要切换窗口,让driver指向新闻页
Java+Selenium+TestNG+Allure

6.4.3 设置窗口大小


//窗⼝最⼤化
driver.manage().window().maximize();
//窗⼝最⼩化
driver.manage().window().minimize();
//全屏窗⼝
driver.manage().window().fullscreen();
//⼿动设置窗⼝⼤⼩
driver.manage().window().setSize(new Dimension(1024, 768));

6.5 等待

6.5.1 强制等待

优点:代码简单

缺点:影响运行效率,浪费大量时间


Thread.sleep();

6.5.2 隐式等待

隐式等待是⼀种智能等待,他可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码继续执⾏,直到超时没找到元素才会报错。


 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));

隐式等待作⽤域是整个脚本的所有元素。即只要driver对象没有被释放掉(driver.quit()),隐式等待就⼀直⽣效(全局生效).
但是隐式等待也有缺点,他只能查找元素是否存在,而不管元素对不对.而且只能查找元素
就像下方代码:


//等待机制的隐式等待
    //隐式等待只是查找元素,并不关注元素结果对不对,只要是有结果,就继续执行
    public void test13() throws InterruptedException {
       createDriver();
       driver.findElement(By.cssSelector("#kw")).sendKeys("邓紫棋");
       driver.findElement(By.cssSelector("#su")).click();
        Thread.sleep(3000);
       driver.findElement(By.cssSelector("#\31  > div > div > div > div > div > div.header-wrapper_3m6nI > div.cos-row.row-text_1L24W.row_4WY55 > div > div > div.cos-flex.cos-items-center > div.title-wrapper_XLSiK > a > div > p > span > span"));
       driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        //隐式等待,查找后发现有"#kw",所以不管.clear是否执行完成,就继续查找下一个元素是否存在
        driver.findElement(By.cssSelector("#kw")).clear();
        //隐式等待,查找后发现有"#kw",所以不管.sendKeys是否执行完成,就继续查找下一个元素是否存在
        driver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        //隐式等待,查找后发现有"#su",所以不管.click是否执行完成,就继续查找下一个元素是否存在
        driver.findElement(By.cssSelector("#su")).click();
        Thread.sleep(3000);
 
        //如果我们不强制等待上述的三个指令执行完成的话,那么迪丽热巴这个词条可能还没完成输入(sendKeys("迪丽热巴");),点击查询按钮(.click();),隐式等待就已经查询完毕了
        //此时迪丽热巴词条还没有进行搜索,就结束,所以还是会返回邓紫棋
 
        //Thread.sleep(3000);就是为了等待 driver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        // driver.findElement(By.cssSelector("#su")).click();执行完毕,更新#31  > div > div > div > div > div > div.header值为迪丽热巴
        WebElement ele=driver.findElement(By.cssSelector("#\31  > div > div > div > div > div > div.header-wrapper_3m6nI > div.cos-row.row-text_1L24W.row_4WY55 > div > div > div.cos-flex.cos-items-center > div.title-wrapper_XLSiK > a > div > p > span > span"));
        System.out.println(ele.getText());
        driver.quit();

6.5.3 显式等待

显⽰等待也是⼀种智能等待,在指定超时时间范围内只要满⾜操作的条件就会继续执⾏后续代码
显式等待可以

elementToBeClickable:等待直到指定的元素在页面上可见并且可以被点击


 WebDriverWait wait=new WebDriverWait(driver,Duration.ofSeconds(3));
 wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));

等待某个元素的文本内容为 “预期文本”(就是看括号内文本在不在前端页面中)


wait.until(ExpectedConditions.textToBe());

presenceOfElementLocated(By locator) 是 ExpectedConditions 类中的一个方法,用于显式等待某个元素出现在页面的 DOM 中。这个方法并不保证元素是可见的或可交互的,只是确保元素已经存在于页面的 DOM 结构中


 wait.until(ExpectedConditions.presenceOfElementLocated())

6.6 弹窗

弹窗不属于web页面元素,所以就没办法定位元素,这里就要使用Alert类


Alert alert = driver.switchTo.alert();
//确认
alert.accept()
//取消
alert.dismiss()

6.7 文件上传

点击⽂件上传的场景下会弹窗系统窗⼝,进⾏⽂件的选择。
selenium⽆法识别⾮web的控件,上传⽂件窗⼝为系统⾃带,⽆法识别窗⼝元素
但是可以使⽤sendkeys来上传指定路径的⽂件,达到的效果是⼀样的


WebElement ele = driver.findElement(By.cssSelector("body > div > div > 
input[type=file]"));
//输入文件本地存储的路径即可
ele.sendKeys("D:\selenium2html\selenium2html\upload.html");

6.7.1文件操作工具类示例


package com.file;

import java.io.*;

public class ReadWriteFileUtils {

    // 写入字节数组到文件
    public static void writeByte(byte[] data, File file) {
        try (FileOutputStream fos = new FileOutputStream(file);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            bos.write(data, 0, data.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 从文件读取字节数组
    public static byte[] readByte(File file) {
        byte[] data = null;
        try (FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis)) {
            data = new byte[(int) file.length()];
            bis.read(data, 0, data.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
}

6.8 关闭和退出


//表示关闭当前标签页
driver.close();
//断开连接,关闭driver对象
driver.quit();

6.9 代理配置工具类示例


package com.proxy;

import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeOptions;

public class ProxyUtils {

    // 设置代理
    public static void setProxy(ChromeOptions options, boolean enableProxy) {
        if (enableProxy) {
            String proxyAddress = "101.200.127.149:3129";
            Proxy proxy = new Proxy();
            proxy.setHttpProxy(proxyAddress);
            options.setProxy(proxy);
        }
    }
}

6.10 随机用户代理工具类示例


package com.useragent;

import java.util.Random;

public class UserAgent {

    public static String getUserAgentWindows() {
        String[] userAgents = {
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0"
        };
        Random random = new Random();
        return userAgents[random.nextInt(userAgents.length)];
    }
}

6.11 截图并保存为文件


// 截图并保存为文件
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile, new File("/path/to/screenshot.png"));


© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...