写作论坛系统自动化测试、性能测试

1.自动化测试的功能

测试的功能:用已注册账号登录、文章列表的查看、文章具体内容的查看、写文章并且发布文章、删除文章、查看自己的文章、注销、注册功能.

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

2.自动化代码编写

2.1.添加相关依赖:

<dependency>
			<groupId>org.seleniumhq.selenium</groupId>
			<artifactId>selenium-java</artifactId>
			<version>4.0.0</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.13.0</version>
		</dependency>
		<dependency>
			<groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.junit.platform</groupId>
			<artifactId>junit-platform-suite</artifactId><version>1.8.2</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.junit.platform</groupId>
			<artifactId>junit-platform-reporting</artifactId><version>1.8.2</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

2.2 建立测试文件包、类。

@suit测试用包导入测试类时需要注意包和包下面类的命名(包名包含TEST/tests,类名包含Test/tsets),不然无法找到包下面对应的测试类。

在这里插入图片描述

2.3 测试类具体分析

2.3.1 启动和结束类(公共类StartEndTest):

1.创建驱动,控制每次测试的驱动启动和结束.
2. 保存测试截图类,用于测试期间对功能界面的截图,通过截图查看bug.
3.截图保存在项目中,以时间和类名来保存,这样可以清晰看到是那个类出现了bug.清晰看到是那个类出现了bug.

2.3.2 登录测试测试(BlogloginTest):

1.创建驱动,并打开页面
2. 测试页面是否正常打开
3. 测试正常登录:多参数测试
4. 测试异常登录:用户名/密码错误的情况(此处不测null)
5. 注意测试的顺序,使用Order注解指定,否则可能会因为执行顺序不对导致测试失败
6. 注意清空内容后才能再次输入用户名以及密码
7. 通过截图把测试页面放到测试文件中,可以查看具体测试页面。

2.3.3 文章列表展示页测试(BlognumNotnuullTest)

1.检测页面的博客数量不为0.
2.检测文章页面显示是否正确.
3.检测用户登录的用护栏页面显示是否正确。
4.检测用户的显示信息是否正确.
5. 通过截图把测试页面放到测试文件中,可以查看具体测试页面的bug。

2.3.4 发布文章页面测试(WriteBlogTest)

1.测试编辑页是否可以正确打开
2.测试文章是否可以正常发布,页面展示是否正确。
3.测试“写文章”按钮是否可以正常使用
4.发布完成文章后,回到文章列表页。
5.文章列表页是否更新了文章列表。

2.3.5 查看文章详情页面测试(BlogDtilTest)

1.测试详情页的正确打开。
2.查看文章详情页的博客作者是否准确。
3.查看文章详情是否正确。
4.发布完成文章后,不要回到文章列表页。

2.3.6 删除文章页面测试(DelBlogTest)

1.点击删除按钮,功能是否正确。
2.删除文章之后,系统是否是跳转页码。
3.文章详情页面是否更新了文章信息。

2.3.6 注销系统测试(BlogOutTest)

1.点击注销按钮,功能是否正确。
2.注销之后,页面是够跳转到了登录页面。

2.3.7 注册用户测试(BlogRegisTest)

1.登录页面的注册按钮是否功能正确。
2.注册页面是否正确显示。
3.输入用户信息符合规范是否能注册成功。
4.输入用户信息不全,错误是否能注册成功。
5.注册成功之后,是否跳转登录页面。
6.注册成功之后,能否用注册账号登录。

2.3.8 测试套件(RunSuit)

测试套件的运行,使用的是以测试类作为执行顺序的方式。


3.测试代码

代码地址请点


3.1 初始化driver和关闭driver代码

用@beforeall和@afterall标注,getScreenShot函数是截图方法,对每个功能自动化测试时,会对页面截图(截图文件按天来区分),查看页面是否符合标准。

public class StartEndTest {

    public static ChromeDriver chromeDriver;
    @BeforeAll
    static void setUp(){
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.addArguments("--remote-allow-origins=*");
        chromeDriver=new ChromeDriver(chromeOptions);
    }
    @AfterAll
    static void Down(){
        chromeDriver.quit();
    }
    /*
     * 保存现场<截图>
     * 把所有用例的执行结果进行保存
     * 注意:保存的屏幕截图的名字应该是动态生成的,否则会进行图片的覆盖
     */
    // 获取动态文件名
    public static List<String> getTime() {
        // 期望的时间格式:20240223-时间(到毫秒)
        // 也就是说:进行时间的格式化
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        String fileName = sim1.format(System.currentTimeMillis());
        // 希望文件按天的维度进行文件夹的分类保存
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd");
        String dirName = sim2.format(System.currentTimeMillis()); // 文件夹的名字
        // 使用链表进行保存
        List<String> list = new ArrayList<>();
        list.add(dirName);
        list.add(fileName);
        return list;
    }

    // 为了区分是哪个用例返回的,可以加上用例的名称进行保存
    public static void getScreenShot(String str) throws IOException {
        List<String> list = getTime();
        // 文件保存路径:dirName+fileName
        // ./指的是当前路径,这里来说就是BlogAutoTest目录下
        // 如果目前期望的路径:./src/test/java/com/blogWebAutoTest/dirName/fileName
        // 注意图片保存的路径以及名称!
        String fileName = "./src/test/java/com/example/"
                + list.get(0) + "/" + str + "_" + list.get(1) + ".png"; // 保存的路径+名称
        File scrFile = chromeDriver.getScreenshotAs(OutputType.FILE); // 获取到的屏幕截图
        // 把屏幕截图生成的文件放到指定路径下
        FileUtils.copyFile(scrFile,new File(fileName));
    }
}

3.2 登录测试

测试成功和失败,分别通过参数化的文件来修改登录的用户来控制登录成功和失败。

//测试登录(成功&失败)
    @Order(1)
    @ParameterizedTest
    @CsvFileSource(resources = "/Blog/LoginSuccess.csv")
    void LoginSuccess(String username, String password, String blog_list_url) throws IOException {
        //登录页面url
        chromeDriver.get("http://localhost:8080/blog_login.html");
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //检查页面是否正确
        chromeDriver.findElement(By.cssSelector("#username"));
        chromeDriver.findElement(By.cssSelector("#password"));
        chromeDriver.findElement(By.cssSelector("#submit"));
        getScreenShot(getClass().getName());
        //输入用户名
        chromeDriver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //输入密码
        chromeDriver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(password);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //点击登录
        chromeDriver.findElement(By.cssSelector("#submit")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //登录后的页面url
        String current_url = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //判断登录的用户名与页面的显示用户名是否相同
        Assertions.assertEquals(current_url, blog_list_url);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String current_username = chromeDriver.findElement(By.xpath("/html/body/div[2]/div[1]/div/h3")).getText();
        Assertions.assertEquals(current_username,username);
        getScreenShot(getClass().getName());
    }

3.3 注册功能测试

注册一个新的账号,再用账号进行登录操作

@ParameterizedTest
    @CsvFileSource(resources = "/Blog/LoginReg.csv")
    void reg(String username,String pas1,String pas2,String login_url,String list_url){
        //登录页面url
        chromeDriver.get("http://localhost:8080/blog_login.html");
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //注册按钮
        chromeDriver.findElement(By.cssSelector(".r > a:nth-child(1)")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //输入用户名
        chromeDriver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //输入2次密码
        chromeDriver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(pas1);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        chromeDriver.findElement(By.xpath("//*[@id=\"password2\"]")).sendKeys(pas2);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //点击提交,回到登录页面
        //判断url
        chromeDriver.findElement(By.cssSelector("#submit")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        chromeDriver.switchTo().alert().accept();
        String current_url = chromeDriver.getCurrentUrl();
        Assertions.assertEquals(current_url,login_url);

        //输入用户名
        chromeDriver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //输入密码
        chromeDriver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(pas1);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //点击登录
        chromeDriver.findElement(By.cssSelector("#submit")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //登录后的页面url
        String currnet_listurl = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //判断登录的用户名与页面的显示用户名是否相同
        Assertions.assertEquals(currnet_listurl, "http://localhost:8080/blog_list.html");
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String current_username = chromeDriver.findElement(By.xpath("/html/body/div[2]/div[1]/div/h3")).getText();
        Assertions.assertEquals(current_username,username);

        chromeDriver.findElement(By.xpath("/html/body/div[1]/a[4]")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }

3.4 文章列表页测试

通过判断文章数量不为0来表示列表页

    @Test
    @Order(2)
    void numBer() throws IOException {

        //判断页面显示是否正确
        String msg = chromeDriver.findElement(By.cssSelector(".card > h3:nth-child(2)")).getText();
        Assertions.assertNotNull(msg);
        //判断页面的博客数量不为0
        int num = chromeDriver.findElements(By.xpath("/html/body/div[2]/div[2]/div[1]")).size();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertNotEquals(0,num);
        getScreenShot(getClass().getName());
    }

3.5 写文章测试

记录写之前的一个文章数量,写完之后刷新页面,获取到页面文章的数量,对比判断是否有新文章。

 @ParameterizedTest
    @CsvFileSource(resources = "/Blog/write.csv")
    void Write_Blog(String detail_url,String title) throws InterruptedException, IOException {

        chromeDriver.findElement(By.cssSelector(".nav > a:nth-child(5)")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String cu_url = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertEquals(cu_url,detail_url);
//		chromeDriver.findElement(By.cssSelector("#title")).sendKeys(title);
//		chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //通过js方式输入内容
        ((JavascriptExecutor)chromeDriver).executeScript("document.getElementById(\"title\").value=\"测试用例\"");
        sleep(3000);
        chromeDriver.findElement(By.cssSelector("#submit")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        chromeDriver.navigate().refresh();
        String nowtitle = chromeDriver.findElement(By.cssSelector("div.blog:nth-child(1) > div:nth-child(1)")).getText();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertEquals(title,nowtitle);
        getScreenShot(getClass().getName());

    }

3.6查看文章内容测试

@ParameterizedTest
    @CsvFileSource(resources = "/Blog/detail.csv")
    void BlogDtil(String name, String detail_url){

        chromeDriver.findElement(By.cssSelector("div.blog:nth-child(1) > a:nth-child(4)")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String cu_url = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String detail_name = chromeDriver.findElement(By.cssSelector(".blog-content > h3:nth-child(1)")).getText();
        Assertions.assertEquals(name,detail_name);
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        if(cu_url.contains(detail_url)) {
            System.out.println("测试通过");
        } else {
            System.out.println(cu_url);
            System.out.println("测试不通过");
        }
    }

3.7 删除文章测试

@ParameterizedTest
    @CsvFileSource(resources = "/Blog/delete.csv")
    void delBlog(String blog_list_url){

        chromeDriver.findElement(By.cssSelector(".nav > a:nth-child(8)")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        String nowtitle = chromeDriver.findElement(By.cssSelector("div.blog:nth-child(1) > div:nth-child(1)")).getText();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertNotEquals("测试用例",nowtitle);
        //登录后的页面url
        String current_url = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //判断登录的用户名与页面的显示用户名是否相同
        Assertions.assertEquals(current_url, blog_list_url);
        //判断页面的数量
        int number2 = chromeDriver.findElements(By.xpath("/html/body/div[2]/div[2]/div[1]")).size();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        Assertions.assertNotEquals(0,number2);
    }

3.8 注销功能测试

@ParameterizedTest
    @CsvFileSource(resources = "/Blog/delete.csv")
    void out(String url,String url2){
        chromeDriver.findElement(By.cssSelector(".nav > a:nth-child(7)")).click();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //判断url 是否是登录页面
        String current_url = chromeDriver.getCurrentUrl();
        chromeDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //判断登录的用户名与页面的显示用户名是否相同

        if(current_url.contains(url2)) {
            System.out.println("测试通过");
            System.out.println(current_url);
            System.out.println(url2);
        } else {
            System.out.println(current_url);
            System.out.println(url2);
            System.out.println("测试不通过");
        }
    }

3.9 测试套件

测试整个系统从开始到结尾的功能的整个执行过程

@Suite
//@SelectPackages(value = {"com.example.demo.TESTall"})
//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@SelectClasses({BlogloginTest.class, BlognumNotnuullTest.class, WriteBlogTest.class
                , BlogDtilTest.class, DelBlogTest.class,BlogMyAtcTest.class,BlogOutTest.class
                ,BlogRegisTest.class})
public class RunSuit {
}

4.代码运行结果:

在这里插入图片描述

5.小结

1)一定要关注测试用例的执行顺序问题
2)对于页面的检查一定要到位,如检查元素是否存在确保页面的正确性
3)注意多参数测试的页面导航问题
4)发现:当多参数(多用户登录)时就会出现高并发的服务器错误情况,该情况需要关注,交给开发人员处理。
5)注意:一定要关注执行顺序!
6)因为列表页等的测试是需要在登录成功后才能抵达的,所以在进行登录页面测试的最后一步应该是登录成功的状态,这样子是为了确保列表页等能够正确进入测试。【并不是绝对,但是需要进行关注】
7)驱动关闭的位置要注意,只有最后一个用例结束之后才进行关闭。
8)为了把所有的用例的执行结果保存下来,方便后续查错或查看,也就是保存现场,此时就需要直接在公共类中进行该方法的定义。
9)注意屏幕截图保存的方式:动态时间戳并进行时间格式化,然后期望按照某种维度(天、周)以文件夹的方式进行保存。
10)@SelectClasses的参数是可以指定执行类的顺序的(注意是类的顺序,不是用例的顺序)
11)获取元素的时候建议获取固定的元素,如时间、标题等;内容不建议获取,因为是动态的。然后元素的路径是不可变的,所以可以使用xpath来进行元素的定位。
12)可以适当关注用例执行时间,如果时间过长就需要考虑是我们自己写的测试用例的问题还是程序真的有性能问题呢
13)为了避免遗漏or遗忘驱动释放的位置,可以单独写一个类来存放驱动释放,然后直接放到套件测试类的最后就行。(注意命名Test结尾)
14)测试用例并不是越多越好

6.性能测试

使用LoadRunner进行简单性能测试:针对登录功能进行简单的性能测试。包括并发测试,响应时间测试,事务响应测试,点击率测试,吞吐率测试,电脑资源利用率等。在实现的过程中,插入集合点,事务以及检查点等,并通过设置来实现用户的并发操作。

6.1登录脚本录制(Virtual User Generator)

设置访问地址以及脚本储存位置。
在这里插入图片描述

6.2 登录脚本加强,脚本编译(Virtual User Generator)

1.删除与登录无关的脚本代码,只剩登录的脚本代码。
2.登录脚本设置了参数化,可以设置多个用户登录。
3.添加了登录的事务功能。
4.设置了检查点(检查点在请求URL之前)。
5.脚本测试通过。

在这里插入图片描述
在这里插入图片描述

6.3 登录运行场景设置(Controller)

1).设置虚拟登录用户,启动Controller。

在这里插入图片描述

2).对运行场景进行设置。

在这里插入图片描述

3).运行场景,查看测试图表。

在这里插入图片描述

6.4 在Analysis中查看性能报告以及报表。

在表中可以看到一些性能指标:吞吐量,吞吐率,点击率,平均点击率,标准偏差以及http响应等。
在这里插入图片描述
点击率报告:
在这里插入图片描述
吞吐量:
在这里插入图片描述
每秒事务数:
在这里插入图片描述

6.5 问题:

使用VUG编写脚本时,设置检查点查找用户名时,讲检查点设置在检查函数之后。直接用用户名来当查找元素会显示not find。
解决:将检查点设置在检查函数之前,就不会报错。在检查点的函数中使用参数化来代替,Text={user},这样就能查找到。
在这里插入图片描述
使用VUG编写脚本时,通过参数化设置用户密码时看不到登录用户的用户名和密码。
解决:在VUG的设置的日志里面打开查看扩展日志,同时设置运行次数,即可看到登录了几个用户。
在这里插入图片描述在这里插入图片描述
查看分析报告时,单张报告表不够突出问题。
解决:在Analysis中使用merge功能将多张表合并在一起。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值