【自动化测试】技术交流论坛


前言

本篇使用Selenium3+Junit5对个人技术交流论坛进行简单的自动化测试,如有错误,请在评论区指正,让我们一起交流,共同进步!



本文开始

1. 项目基础描述

项目介绍:
技术交流论坛基于 Spring Boot,MyBatis, MySQL等技术实现的一个前后端分离的一个项目;
主要功能页有:登录页、注册页、技术交流论坛列表展示页,帖子编辑发布和个人中心页。
测试主要页面:登录页面,注册页面,列表展示页面以及帖子编辑发布页,个人信息展示,退出操作功能。【都是基于常用的主要页面进行的】

2. 编写手工测试用例

在这里插入图片描述

3. 测试用例转自动化测试用例

3.1 前置准备操作

3.1.1 配置环境:

创建Maven项目,配置pom.xml文件

 <dependencies>
        <!--添加selenium依赖-->
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!--保存屏幕截图的包-->
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!--Junit5-->
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
        </dependency>
    </dependencies>

3.1.2 配置使用的公共类

原因:
1.每个测试用例都需要驱动,使用前置方法设置,后置方法释放驱动资源
2.配置一些公共方法,方便测试使用;如:截图方法,进入登录状态方法等

public class AutoTestUtils {
    //每次测试都需要驱动,写一个公共类,实现代码复用
    public static WebDriver webDriver;

    @BeforeAll
    public static void SetUp() {
        if(webDriver == null) {
            System.setProperty("webdriver.chrome.driver","C:\\Program Files\\Google\\Chrome\\Application\\chromedriver.exe");
            webDriver = new ChromeDriver();
        }
    }
    @AfterAll
    static void TearDown() {
        webDriver.quit();
    }
     /**
     *  截图方法
     */
    public static void saveScreenshot(WebDriver driver, String fileName) throws IOException {
        File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);

        // 确保截图目录存在
        File screenshotDir = new File(SCREENSHOT_DIR);
        if (!screenshotDir.exists()) {
            screenshotDir.mkdirs();
        }
        // 拼接完整的文件路径
        File destFile = new File(screenshotDir, fileName);
        // 复制文件
        FileUtils.copyFile(srcFile, destFile);

        System.out.println("Screenshot saved as " + destFile.getAbsolutePath());
    }
    /**
     * 获取当前截图时间-字符串
     * @return
     */
    public static String getCurrentShotTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
        String timeName = sdf.format(System.currentTimeMillis());
        return timeName;
    }

    /**
     * 封装登录方法,方便以后调用;以后测试需要在登录状态下使用
     */
    public static void login() throws InterruptedException {
        //1.打开登录页面
        webDriver.get("http://8.130.77.131:58080/sign-in.html");
        //2.清楚之前的账号密码
        webDriver.findElement(By.cssSelector("#username")).clear();
        webDriver.findElement(By.cssSelector("#password")).clear();
        //3.找到输入框,输入正确的账号和密码
        webDriver.findElement(By.cssSelector("#username")).sendKeys("zhangsan");
        webDriver.findElement(By.cssSelector("#password")).sendKeys("123");
        //4.点击登录按钮
        webDriver.findElement(By.cssSelector("#submit")).click();
        sleep(3000);
    }
 }

3.1.3 项目目录 + 截图

在这里插入图片描述

3.2 编写自动化测试脚本

3.2.1 注册自动化测试

  • 注册界面测试 - RegTest
    1.获取驱动,打开注册界面
    2.找到输入框,输入账号,昵称,密码,确认密码
    3.点击确认协议
    4.校验是否注册成功
    5.注册失败,截图查看失败原因
成功注册
	/**
     * 成功注册的情况
     */
    @Order(1)
    @ParameterizedTest
    @CsvSource(value = {"lisi,lisi,123,123"})
    public void regSuccessTest(String username, String nickname,
                               String password, String passwordRepeat) throws InterruptedException {
        //显示等待
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //1.打开注册页面
        webDriver.get("http://8.130.77.131:58080/sign-up.html");
        //2.找到输入框,输入注册的账号和密码
        webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
        webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
        webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
        webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(passwordRepeat);
        //4.点击同意协议
        webDriver.findElement(By.cssSelector("#policy")).click();
        //5.点击注册按钮
        webDriver.findElement(By.cssSelector("#submit")).click();
        //5.验证是否跳转到登录页
        sleep(2000);
        String currentUrl = webDriver.getCurrentUrl();
        Assertions.assertTrue(currentUrl.contains("sign-in.html"));//查看是否包含关键词
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }
注册失败情况

【注】编写的测试用例太多,取几个演示

 @Order(2)
    @ParameterizedTest
    @CsvSource(value = {"wangwu,wangwu,123,1234"})
    public void regFailTest(String username, String nickname,
                            String password, String passwordRepeat) throws InterruptedException, IOException {
        //显示等待
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //1.打开注册页面
        webDriver.get("http://8.130.77.131:58080/sign-up.html");
        //2.找到输入框,输入注册的账号和密码
        webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
        webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
        webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
        webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(passwordRepeat);
        //3.错误截图,生成当前截图时间
        String timeName = getCurrentShotTime();
        String fileName = "regFail" + timeName + ".png";
        sleep(2000);
        saveScreenshot(webDriver,fileName);
        //4.点击同意协议
        webDriver.findElement(By.cssSelector("#policy")).click();
        //5.点击注册按钮
        webDriver.findElement(By.cssSelector("#submit")).click();
        String timeName2 = getCurrentShotTime();
        String fileName2 = "regClickFail" + timeName2 + ".png";
        sleep(2000);
        saveScreenshot(webDriver,fileName2);
    }

    /**
     * 昵称为空 + 密码错误
     */
    @Order(3)
    @ParameterizedTest
    @CsvSource(value = {"laoliu,laoliu,123,123"})
    public void regNickNameNullTest(String username, String nickname,
                            String password, String passwordRepeat) throws InterruptedException, IOException {
        //显示等待
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //1.打开注册页面
        webDriver.get("http://8.130.77.131:58080/sign-up.html");
        //2.找到输入框,输入注册的账号和密码
        webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
        webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
        webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(passwordRepeat);
        //3.点击同意协议
        webDriver.findElement(By.cssSelector("#policy")).click();
        //4.点击注册按钮
        webDriver.findElement(By.cssSelector("#submit")).click();
        //5.失败截图
        String timeName = getCurrentShotTime();
        String fileName = "regNickNameNull" + timeName + ".png";
        sleep(2000);
        saveScreenshot(webDriver,fileName);
    }

测试结果:

在这里插入图片描述
失败截图查看原因在这里插入图片描述

3.2.2 登录自动化测试

  • 登录界面自动化测试 - LoginTest
    1.获取驱动,打开登录界面
    2.校验正常登录 - 多参数测试,多个测试用例
    3.校验异常登录 - 错误的密码登录
    4.对于多组测试,需要清空上次输入的内容
    5.使用注解保证测试的顺序
成功登录情况
	/**
     * 正常登录情况
     *  参数化登录:使用注解@CsvSource
     */
    @Order(1)
    @ParameterizedTest
    @CsvSource({"zhangsan,123", "张三,123"})
    public void logSuccessTest(String name, String password) throws InterruptedException {
        //显示等待
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //1.打开登录页面
        webDriver.get("http://8.130.77.131:58080/sign-in.html");
        //2.清楚之前的账号密码
        webDriver.findElement(By.cssSelector("#username")).clear();
        webDriver.findElement(By.cssSelector("#password")).clear();
        //3.找到输入框,输入正确的账号和密码
        webDriver.findElement(By.cssSelector("#username")).sendKeys(name);
        webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
        //4.点击登录按钮
        webDriver.findElement(By.cssSelector("#submit")).click();
        //5.验证是否跳转到列表页
//        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        sleep(2000);
        String currentUrl = webDriver.getCurrentUrl();
        Assertions.assertEquals("http://8.130.77.131:58080/index.html", currentUrl);
        //6.多次登录,每次登录后退回登录页面
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        webDriver.navigate().back();
    }
失败登录
 	/**
     * 异常登录情况
     *  输入错误的账号+密码
     */
    @Disabled // 不运行注释
    @Order(2)
    @ParameterizedTest
    @CsvSource(value = "zhangsan,1234")
    public void failLogin(String name, String password) throws InterruptedException, IOException {
        //1.打开登录页面
        webDriver.get("http://8.130.77.131:58080/sign-in.html");
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //2.输入账号:zhangsan,密码:1234
        webDriver.findElement(By.cssSelector("#username")).sendKeys(name);
        webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
        Thread.sleep(2000);
        //3.点击提交
        webDriver.findElement(By.cssSelector("#submit")).click();
        //4.获取提示信息文本:用户或密码错误
        String text = webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText();
        System.out.println("提示信息:" + text);
        //5.生成当前截图时间
        String timeName = getCurrentShotTime();
        String fileName = "loginFail" + timeName + ".png";
        //6.调用截图方法
        sleep(3000);
        saveScreenshot(webDriver,fileName);
    }

运行结果

在这里插入图片描述
错误情况截图在这里插入图片描述

3.2.3 列表页自动化测试

  • 遇到的bug:
    • 操作:登录状态查看帖子列表
    • 出现异常: no such element
    • 原因:首页帖子页面还未渲染完毕,就捕获文本元素
    • 解决:使用隐式等待
      如:webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
登录状态下查看列表
	 /**
     * 登录状态查看帖子列表
     *  出现异常: no such element
     *  原因:首页帖子页面还未渲染完毕,就捕获文本元素
     *  解决:使用显示等待
     */
    @Test
    @Order(1)
    public void showSuccess() throws InterruptedException {
        //1.登录操作
        login();
        //2.显示首页帖子列表,查看第一天帖子信息
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String actual_text = webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).getText();
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //3.断言校验
        Assertions.assertEquals("Java是如何练成的?", actual_text);
    }
未登录状态下查看帖子页
    /**
     * 未登录页不能够查看帖子页
     *  能够显示
     */
    @Test
    @Order(2)
    public void showFail() throws InterruptedException, IOException {
        //1.不进行登录,直接查看帖子页面
        webDriver.get("http://8.130.77.131:58080/index.html");
        //2.显示列表页,使用截图查看
        String timeName = getCurrentShotTime();
        String fileName = "showFail" + timeName + ".png";
        //3.调用截图方法
        sleep(3000);
        saveScreenshot(webDriver,fileName);
    }

运行结果

在这里插入图片描述
未登录错误情况截图
在这里插入图片描述

3.2.4 帖子编辑自动化测试

  • 遇到bug:
    • 操作:登录状态下进行帖子编辑
    • 出现异常:ElementClickInterceptedException: element click intercepted: Element is not clickable at point (939, 1108)
    • 原因:页面是异步加载,点击按钮未加载,就进行了的点击,导致元素点击中断,找不到点击位置
登录状态下进行帖子编辑
 	/**
     * 登录状态下进行帖子编辑
     *  出现异常:ElementClickInterceptedException: element click intercepted: Element is not clickable at point (939, 1108)
     *  原因:页面是异步加载,点击按钮未加载,就进行了的点击,导致元素点击中断,找不到点击位置
     */
    @Test
    public void editSuccess() throws InterruptedException, IOException {
        //1.进入登录状态
        login();
        //2.点击编辑帖子
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        webDriver.findElement(By.xpath("//*[@id=\"forum-content\"]/div[1]/div/div/div[2]/div/a[1]")).click();
        //3.输入帖子标题
        webDriver.findElement(By.xpath("//*[@id='article_post_title']")).sendKeys("EditTest");;
        sleep(3000);
        //4.查看发布帖子按钮
        String text = webDriver.findElement(By.xpath("//*[@id='article_post_submit']")).getText();
        Assertions.assertEquals("发 布", text);
        sleep(3000);
        webDriver.findElement(By.xpath("/html/body/div[1]/div/div[1]/div[2]/div/div/div[2]/div/a")).click();
        String text1 = webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText();
        System.out.println("提示:" + text1);
        //5.截图查看
        String time = getCurrentShotTime();
        String fileName = "editSuccess" + time + ".png";
        sleep(2000);
        saveScreenshot(webDriver, fileName);
    }
未登录状态
    /**
     * 未登录状态,直接提示报错信息
     */
    @Test
    public void editFail() throws InterruptedException, IOException {
        //1.直接进入编辑页面
        webDriver.get("http://8.130.77.131:58080/index.html");
        //2.截图获取信息
        String time = getCurrentShotTime();
        String fileName = "editFail" + time + ".png";
        sleep(2000);
        saveScreenshot(webDriver, fileName);
    }

运行结果:

在这里插入图片描述
没有输入帖子内容,错误提示截图
在这里插入图片描述

3.2.5 个人中心自动化测试

登录状态下获取个人信息
 	/**
     * 登录状态下,获取个人信息
     */
    @Test
    public void successShowPersonInfo() throws InterruptedException {
        //1.进入登录状态
        login();
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //2.点击个人中心
        webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击个人头像
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        webDriver.findElement(By.cssSelector("#index_user_settings")).click();//下拉列表中,点击个人中心
        sleep(2000);
        //3.获取用户昵称
        String actual_text = webDriver.findElement(By.cssSelector("#setting_input_nickname")).getAttribute("value");
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertEquals("zhangsan", actual_text);
    }
未登录状态获取个人中心
    @Test
    public void failShowPersonInfo() throws InterruptedException, IOException {
        //1.进入列表页
        webDriver.get("http://8.130.77.131:58080/index.html");
        //2.点击个人中心
        webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击个人头像
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        webDriver.findElement(By.cssSelector("#index_user_settings")).click();//下拉列表中,点击个人中心
        //3.截图查看提示
        String timeName = getCurrentShotTime();
        String fileName = "failShowPersonInfo" + timeName + ".png";
        //3.调用截图方法
        sleep(3000);
        saveScreenshot(webDriver,fileName);
    }

运行结果

在这里插入图片描述
未登录状态,错误提示截图在这里插入图片描述

3.2.6 退出功能自动化测试

登录状态下退出
    /**
     * 登录状态点击退出
     */
    @Test
    public void backSucTest() throws InterruptedException {
        //1.进入登录状态
        login();
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //2.点击个人中心
        webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击个人头像
        //3.点击退出
        webDriver.findElement(By.xpath("//*[@id=\"index_user_logout\"]")).click();
        webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //4.回到登录页面校验 “用户登录” 文本
        String login_text = webDriver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2")).getText();
        Assertions.assertEquals("用户登录", login_text);
    }

运行结果:

在这里插入图片描述

4.小结

考虑提升:

  • 可以考虑使用PO模式,现在的代码将获取元素,操作元素,测试元素操作混在了一起,对于后期维护比较困难,使用PO模式改进,可以复用元素代码,让多个人写测试用例的耦合降低,也利用后期的维护工作;

后期注意

  • 需要注意测试的执行顺序,不关注可能报错
  • 对于多参数测试,需要清空上次输入数据,页面回退
  • 测试用例并不是越多越好,覆盖较多功能较好
  • 测试功能会有遗漏的情况,对于测试用例执行顺序会有错误情况

测试优势:

1.使用Junit5单元测试框架中的注释:提高测试的稳定性,提高自动化执行效率;(指定执行测试顺序,指定参数)
2.根据技术交流论坛设计的手工测试用例,对每个测试用例的常用功能实现自动化测试
3.使用工具类每次测试都需要驱动,写一个公共类,实现代码复用
4.使用等待:提高自动化运行效率,提高自动化的稳定性,减小误报的可能性


总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值