【项目测试】共享博客系统

一、项目背景

共享博客系统是一个简单的Web网站项目,使用前后端分离技术来实现的。该项目由博客登录页面、博客列表页、博客详情页、博客编辑页来构建而成的。该项目已经部署到了云服务器中,可以在线上模拟实现登录、查看博客列表、查看博客详情、编辑和删除博客、发布博客、注销账号等一系列功能。

二、项目功能

  • 登陆页面:在登陆页面是用来实现登录功能,这里的账号和密码已经提前写入到了数据库当中。此页面中可以跳转到博客列表页和博客编辑页,登录成功时就会自动跳转到博客列表页
  • 博客列表页:在博客列表页是可以查看所有编辑过的博客记录和发布时间,并可以查看登陆的用户名称,此页面中存在主页,写博客,查看全文等标签,可以跳转到博客详情页,博客编辑页
  • 博客详情页:在博客详情页可以查看博客标题和完整的博客内容,此页面中存在主页,写博客,可以跳转到博客列表页,博客编辑页,而且存在编辑和删除标签,实现博客的更新和删除
  • 博客编辑页:在博客编辑页可以输入标题和博客内容后可以进行发布,发布后会跳转到博客列表页。此页面中存在主页标签,可以跳转到博客列表页

三、对项目进行测试

对项目进行测试时需要从功能测试,性能测试,界面测试,安全测试,易用性测试,界面测试,网络测试来进行测试,但是在共享博客系统主要是围绕着功能测试来实现的

1. 功能测试

先采用手工测试,对登录功能、查看博客列表功能、查看博客详情功能、编辑和删除博客功能、发布博客功能、注销账号功能来测试,排查已有的问题。

脑图

测试用例:
在这里插入图片描述

部分操作步骤

1.1 测试登录操作

登录界面
登陆界面

  • 账号+密码 正确
    在这里插入图片描述
    预期结果:正常跳转界面
    在这里插入图片描述

  • 账号密码为空
    预期结果:登录失败
    在这里插入图片描述

  • 账号或密码错误
    预期结果:登陆失败
    在这里插入图片描述

1.2 测试发布博客

博客编辑页
在这里插入图片描述

  • 编辑博客时标题不为空,内容不为空,点击发布博客按钮
    预期结果:发布成功,跳转到博客列表页并显示在博客列表页
    在这里插入图片描述
  • 当标题为空,内容不为空,点击发布博客按钮
    预期结果:发布失败
    实际结果:发布成功
    在这里插入图片描述

1.3 测试展示博客

  • 登录成功下

预期结果:展示成功
在这里插入图片描述
在这里插入图片描述

  • 登录异常情况下

预期结果:展示博客失败 提示登陆失败
在这里插入图片描述

1.4 测试注销功能

在这里插入图片描述

  • 点击注销功能
    预期结果:返回到登录页面,尝试展示博客时显示未能登录
    在这里插入图片描述
    在这里插入图片描述

2. 使用Selenium进行自动化测试

通过使用Selenium通过定位元素的Selector,和屏幕截图等方式来进行自动化测试操作,实现对项目的进一步完善。主要的测试点围绕着登录功能、查看博客列表功能、查看博客详情功能、编辑和删除博客功能、发布博客功能、注销账号功能来测试,并进行查找和修复已有Bug来完善自己的项目。

脑图

测试用例:
在这里插入图片描述

2.1 代码编写步骤

  1. 添加相关依赖pom.xml
  2. 创建一个公共类来同意进行创建驱动和屏幕截图,并创建隐式等待确保可以由足够的时间来查找元素、
  3. 创建一个Run来统一进行代码测试
  4. 创建一个NotLogin类,专门对没有进行登录时对博客列表页,博客详情页,博客发布页来进行测试
  5. 使每一个页面为为一个测试类,成功登录情况下在各个测试类中进行测试用例的编写

2.1.1添加相关依赖pom.xml

<dependencies>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.8.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0</version>
        </dependency>
    </dependencies>

2.1.2 创建公共类

  • 统一创建驱动对象
  • 统一实现屏幕截图功能,注意文件格式,以及命名方式
  • 实现隐式等待,对查找元素统一等待2秒

代码

package common;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;

//创建驱动对象,等待,屏幕截图
public class Utils {
    public static WebDriver driver;//全局变量
    public static int Admin;
    public static WebDriver create(){
        if(driver == null) {
            WebDriverManager.chromedriver().setup();
            ChromeOptions options = new ChromeOptions();
            //允许访问所有链接
            options.addArguments("--remote-allow-origins=*");
            driver = new ChromeDriver(options);

            //等待-- 查找每个元素时都等待2秒
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));
        }
        return driver;
    }
    public Utils() {//未登录用
        driver = create();
    }
    public Utils(String url) {//传url
        //创建驱动对象
        driver = create();
        driver.get(url);
    }

    //屏幕截图
    public void getScreen(String filename) throws IOException {
        //./src/test/img
        //                /2024-XX-XX
        //                            /test01/170025.png
        //                /2024-XX-XX
        //                            /test05/580031.png
        SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat s2 = new SimpleDateFormat("HHmmssSS");
        String dirTime = s1.format(System.currentTimeMillis());
        String fileTime = s2.format(System.currentTimeMillis());
        String file = "./src/test/img" + "" + dirTime + "/" + filename + "/" + fileTime + ".png";
        File f = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(f,new File(file));
    }
}

2.1.3测试NotLogin类
  • 测试:未登录时博客列表页是否提示弹窗,提示没有登陆并返回到登陆页面
  • 测试:未登录时博客详情页是否提示弹窗,提示没有登陆并返回到登陆页面
  • 测试:未登录时是否可以正常访问博客发布页

运行结果

在这里插入图片描述
代码:

public class NotLogin extends Utils {
    String listUrl = "http://111.229.29.41:8080/blog_list.html";
    String Detail = "http://111.229.29.41:8080/blog_detail.html";
    String edit = "http://111.229.29.41:8080/blog_edit.html";

    public void notLoginList() throws IOException, InterruptedException {
        driver.get(listUrl);
        /*出现弹窗错误---不使用
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());出现弹窗错误
        Thread.sleep(2000);*/
        Thread.sleep(2000);
        //出现弹窗
        Alert alert = driver.switchTo().alert();
        alert.accept();
    }
    public void notLoginDetail() throws IOException, InterruptedException {
        driver.get(Detail);
        /*出现弹窗错误---不使用
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());出现弹窗错误
        Thread.sleep(2000);*/
        Thread.sleep(2000);
        //出现弹窗
        Alert alert = driver.switchTo().alert();
        alert.accept();
    }

    public void notLoginEdit() throws IOException {
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());
        driver.get(edit);
    }
}
2.1.4 测试登录页表页
  1. 创建驱动,并打开页面
  2. 测试页面是否正常打开
  3. 正常登录后测试多组元素
  4. 返回上一级目录并清空账号和密码
  5. 测试异常登录:用户名/密码错误的情况
    代码:
public class Login extends Utils {
    public static String url = "http://111.229.29.41:8080/blog_login.html";
    public Login() {
        super(url);
    }

    //登录页面正确
    public void loginRight() throws InterruptedException, IOException {
        //验证主页
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        //验证登录页面
        driver.findElement(By.cssSelector("body > div.container-login > div > h3"));
        //验证博客页面
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)"));
        //获取标题
        System.out.println(driver.getTitle());
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());
        Thread.sleep(2000);
    }

    //登录成功
    public void loginSuc() throws InterruptedException, IOException {
        //输入账号;密码
        driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        driver.findElement(By.cssSelector("#submit")).click();
        //检验是否登录成功
        //1.查看标题
        driver.findElement(By.cssSelector("body > div.nav > span"));
        //2.查看主页标签
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        //3.查看查看全文标签
        driver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a"));
        Thread.sleep(2000);
        //获取标题
        System.out.println(driver.getTitle());
        //获取url
        String url = driver.getCurrentUrl();
        //断言
        assert url.equals("http://111.229.29.41:8080/blog_list.html");
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());
        //返回上一页
        driver.navigate().back();
    }

    //登录失败
    public  void loginFail() throws InterruptedException, IOException {
        //刷新
        driver.navigate().refresh();
        driver.findElement(By.cssSelector("#username")).sendKeys("lisi");
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //检验是否登录成功
        //获取url
        System.out.println(driver.getCurrentUrl());
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());
    }
}
2.1.5 测试博客列表页
  1. 测试博客列表页是否可以正常打开
  2. 正常显示博客列表页:测试多组元素
  3. 测试列表页是否可以正常跳转到博客详情页
  4. 测试跳转到的博客详情页内容是否正确

代码:

public class BlogList extends Utils {
    public BlogList() {
        super("http://111.229.29.41:8080/blog_list.html");
    }
    //登录成功
    //列表页显示成功
    public void listSuc() throws InterruptedException, IOException {
        //1.查看标题
        driver.findElement(By.cssSelector("body > div.nav > span"));
        //2.查看主页标签
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        //3.查看查看全文标签
        driver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a"));
        Thread.sleep(2000);
        //4.获取标题
        System.out.println(driver.getTitle());
        //5.断言url
        String url = driver.getCurrentUrl();
        assert url.equals("http://111.229.29.41:8080/blog_list.html");
        getScreen(Thread.currentThread().getStackTrace()[1].getMethodName());
    }

    //验证--查看全文是否正确
    public void listShowRight(){
        //验证是否跳转成功
        driver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a")).click();
        //----跳转成功
        //验证是否有标题
        driver.findElement(By.cssSelector("body > div.container > div.right > div > div.title"));
        //验证是否有账号名称
        String admin = driver.findElement(By.cssSelector("body > div.container > div.left > div > h3")).getText();
        //验证对自己账号可否有编辑,删除
        if(admin == "lisi"){
            driver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(1)"));
            driver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)"));
        }
        //验证收是否有主页
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        //验证标题
        String url = driver.getTitle();
        assert url.equals("博客详情页");
    }
}
2.1.6 测试登录页表页
  1. 测试详情页的正确打开:有blogId和没有blogId两种情况
  2. 测试有blogId时-测试多组元素
  3. 没有blogId-是否提示错误信息
public class Detail extends Utils {
    //详情页失败
    public void detailFail() throws IOException, InterruptedException {
        driver.get("http://111.229.29.41:8080/blog_detail.html");
        //出现弹窗
        Thread.sleep(2000);//执行太快缓俩秒
        Alert alert = driver.switchTo().alert();
        alert.accept();
    }
    //详情页成功
    public void detailSuc(){
        driver.get("http://111.229.29.41:8080/blog_list.html");
        driver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a")).click();
        //验证是否有标题
        driver.findElement(By.cssSelector("body > div.container > div.right > div > div.title"));
        //验证是否有账号名称
        String admin = driver.findElement(By.cssSelector("body > div.container > div.left > div > h3")).getText();
        //验证对自己账号可否有编辑,删除
        if(admin == "lisi"){
            driver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(1)"));
            driver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)"));
        }
        //验证收是否有主页
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));
        //验证标题
        String url = driver.getTitle();
        assert url.equals("博客详情页");
    }
}
2.1.7 测试博客发布页
  1. 测试编辑页是否可以显示–测试多组元素
  2. 测试博客是否可以正常发布
  3. 测试是否显示在博客列表页
  4. 关闭驱动对象

代码:

public class Edit extends Utils {
    public Edit(){
        super("http://111.229.29.41:8080/blog_edit.html");
    }
    public void EditRight(){
        driver.findElement(By.cssSelector("#submit"));
        driver.findElement(By.cssSelector("body > div.nav > span"));
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)"));
    }
    public void editSuc() throws InterruptedException {
        driver.findElement(By.cssSelector("#title")).sendKeys("测试");
        driver.findElement(By.cssSelector("#submit")).click();
        Thread.sleep(1000);
        //测试是否发布成功
        String title = driver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > div.title")).getText();
        assert title.equals("测试");
    }
}

执行代码:

public class Run {
    public static void main(String[] args) throws InterruptedException, IOException {
        Login login = new Login();
        login.loginRight();
        login.loginSuc();
        login.loginFail();
        BlogList blogList = new BlogList();
        blogList.listSuc();
        blogList.listShowRight();
        Detail detail = new Detail();
        detail.detailFail();
        detail.detailSuc();
        Edit edit = new Edit();
        edit.EditRight();
        edit.editSuc();
        Utils.driver.quit();
    }
}

测试结果:成功
在这里插入图片描述

自动化测试亮点以及难点

难点
在测试过程中出现一些意想不到的问题和Bug,需要花费时间来进行调整和完善,并在跳转和处理弹窗时需要强制等待,以便于代码可以正确识别,避免程序速度过快出现遗漏的请况

亮点:

  1. 只创建一次驱动,避免了资源浪费
  2. 使用了隐式等待,提高了自动化测试的稳定性
  3. 使登录异常和登录成功 分开进行测试,使代码变得更易观
  4. 使用了屏幕截图:方便问题的追溯以及问题的解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值