前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【连珠云弈】网页五子棋版项目测试报告

【连珠云弈】网页五子棋版项目测试报告

作者头像
用户11316056
发布2025-03-07 10:47:11
发布2025-03-07 10:47:11
6600
代码可运行
举报
运行总次数:0
代码可运行

一、项目背景

1.1、项目起源

随着互联网的飞速发展和普及,网络娱乐方式日益多样化。五子棋作为一种传统而经典的棋类游戏,深受广大棋迷的喜爱。然而,传统的五子棋游戏方式往往受限于地点和时间,无法满足人们随时随地进行游戏的需求。因此,开发一款网页版五子棋项目,旨在打破这种限制,让棋迷们能够随时随地通过网络享受五子棋的乐趣。

1.2、市场需求

  1. 便捷性需求:现代人生活节奏加快,对于娱乐方式的需求也更加注重便捷性。网页版五子棋无需下载和安装,只需打开浏览器即可进行游戏,极大地方便了用户。
  2. 社交性需求:网络游戏的社交属性日益凸显,玩家们不仅追求游戏本身的乐趣,还希望在游戏中结交新朋友。网页版五子棋可以提供在线对战功能,满足玩家的社交需求。
  3. 普及性需求:五子棋作为一种传统文化,其普及和传承具有重要意义。网页版五子棋项目的开发,有助于将这一传统文化以更现代化的方式呈现给更多人,推动五子棋的普及和发展。

1.3、项目目标

  1. 开发一款易用的网页版五子棋游戏:游戏界面简洁明了,操作方便快捷,让玩家能够轻松上手并享受游戏乐趣。
  2. 实现在线对战功能:支持玩家在线匹配对手,进行实时对战,增强游戏的互动性和趣味性。
  3. 优化游戏性能和用户体验:通过不断优化游戏算法和界面设计,提高游戏的运行速度和稳定性,为玩家提供更加流畅、舒适的游戏体验。

二、项目功能

2.1 用户管理功能

用户注册与登录:用户可以通过注册页面注册账号,填写用户名、密码等信息进行注册,注册成功后可在登录页面输入账号密码登录。

用户信息管理:系统能够记录用户的相关信息,如用户id、用户名、密码、天梯分数、排位总场次和胜场总场次等,并提供修改密码、查看个人信息等功能。

用户状态管理:通过session管理模块实现用户登录状态的维护,使用户在游戏过程中保持登录状态,直到用户主动退出或超时自动退出。

2.2 游戏对战功能

匹配对战:系统根据用户的天梯分数等信息进行匹配,为玩家找到合适的对手,进入游戏房间进行对战。

实时对战:在游戏房间内,玩家可以进行实时的五子棋对战,双方轮流落子,通过点击棋盘上的空位放置棋子。

胜负判断:系统能够实时检测当前落子位置在横、纵、斜四个方向是否有连续五个相同的棋子,以判断胜负。

三、测试报告

全部的测试用例:

3.1.功能测试

3.1.1注册功能测试

注册已经存在的用户:

与预期结果一致,注册失败!并显示用户名以及被占用。

输入的账号或密码超出规定的长度范围:

代码语言:javascript
代码运行次数:0
复制
drop database if exists gobang;
create database if not exists gobang;
use gobang;
create table if not exists user(
    id int primary key auto_increment,
    username varchar(32) unique key not null,
    password varchar(128) not null,
    score int,
    total_count int,
    win_count int
);

根据MySQL定义的数据表中账号的最多长度是32位,而密码是128位,当我输入的账号超出32位时,系统就会报错,与预期结果一致!

异常注册的情况:

账号为空时:

跟预期结果一致,注册失败!

密码为空时:

我们发现当密码为空时居然注册成功了!这明显跟我们预期不符合的,并且我们之前在定义数据表的时候,password明显是有not null属性的,这是为什么呢?!

账号密码都为空时

我勒个豆,竟然也注册成功了!但是我们已经注册账号为空的时候,下一次再注册账号为空会有用户名已经存在的现象。

解决bug:

问题是在于前端给后端传的数据是 空字符串, jsonvalue的 isNull函数判断有点问题。目前是把条件修改了,判断前端传递过来的是不是一个空串。 这个是后端在处理的时候,提前就要判断处理掉的。

有一个疑问是密码为什么是空,数据库还能插入成功。

是因为前端给后端的是一个空字符串, 并且密码经过md5加密后,并不为空,所以插入是没问题的。 其次是name为何不写,也能注册成功。是因为不写,向后端传的是空字符串,而不是null。

所以,第一个要解决的是,我们用户不写用户名和密码的时候,后端要及时能够检测出来。所以修改了判断条件,得以解决。 第二个疑问是为何不写,sql语句还能执行成功,是由于 空字符串 和 null是有区别的!

当我们在数据库中插入空字符串的账号和密码的时候,插入成功!这也就验证了空字符串和null的区别,也解释了之前账号和密码为空的时候能注册成功的原因。

当我们更改判断条件之后,再来用空账号,密码注册一下(此时已经将数据库中的空账号的用户删除了)

此时,就不能用空账号进行注册了!bug解决完毕!

正常注册:

发现成功跳转到登录页面

与预期结果一致!

测试总结:

通过对注册页面的界面测试和功能测试,得出以下结论:

注册页面的背景图片显示正常,页面中的文字样式,和注册框均能正常显示。除此之外,注册框中的字样、输入框和“提交”按钮也能够正常显示。

正常注册情况,在注册一个并没有注册过的用户名时,可以正常注册成功,并且页面会提示用户“注册成功! 当注册已经注册过的用户时,页面会显示用户名被占用,让用户重新注册!

但是当密码为空时,用户也注册成功了!发现了这个bug。

3.1.2登录功能测试

正确的用户名和密码登录:

登录成功,与预期结果一致!并且账号和密码都能复制粘贴,密码也是隐藏了

异常的用户名和密码登录:

界面会显示用户名密码错误,与预期结果一致!

当跳过登录界面,直接进入游戏房间

预期:找不到用户信息,请重新登录,并跳转到登录界面

测试总结:

通过对登录页面的界面测试和功能测试,得出以下结论:

登录页面的背景图片显示正常,页面中的文字样式,和登录框均能正常显示。

建议:

但当登录失败时,可以具体向用户展示到底是账号错误还是密码错误,便于用户修改

3.1.3.匹配和落子测试

这里匹配和落子测试和界面一起测试

3.2.界面测试

bug:

当用户名字很长的时候 界面就会出现这种重回覆盖的情况

解决措施: 用户名过长最少有两种方式,第一种就是直接截取,比如你的用户名有19位,我只展示10位就行了。剩下的不展示 第二种就是,19位,只展示一部分,当鼠标放上去之后,展示完整的用户名

这里实现了第二种

测试总结

通过测试游戏大厅页面的界面显示和匹配功能,得出以下结论:

游戏大厅页面的左上角“五子棋对战”字样正常显示,背景图片正常显示

玩家信息(用户名、分数、比赛场次、获胜场次)正常显示,

匹配功能正常,两个同级别玩家点击匹配按钮后,会匹配在一起。

并且当有一方五星连珠时,界面会显示游戏胜利/失败

通过对游戏大厅页面的界面测试和功能测试,并未在游戏大厅页面发现bug。

3.3.性能测试

下面我来使用 JMeter 对五子棋项目的登录接口和获取用户信息接口进行简单的性能测试,下面就来介绍五子棋项目性能测试的一个测试流程。

总体测试框架:
3.3.1.利用BeanShell解决乱码问题
3.3.2.添加保存cookie信息

因为用户在登录之后,我们需要从info接口读取消息,所以需要自动保存用户登录的cookie信息

这里直接选择standard即可

3.3.3.添加CSV格式的用户信息

我们为了更加真实的模拟用户登录场景,我们在CSV文件中添加了用户信息以供模拟真实的用户登录场景。

下面的是配置,用username和password表示账号密码,后续直接在body中引用即可。

如下面的登录接口就调用了CSV文件中的账号和密码。

3.3.4.添加同步定时器

我们为了保证线程是并发执行的,我们添加了同步定时器。

3.3.5.创建梯度压测线程组

这里我们创建一个梯度压测线程组(Stepping Thread Group),来慢慢增大我们对这两个接口的并发请求的数量,以达到性能测试的目的。

3.3.6.生成测试报告

我们发现有一小部分测试用例出现的bug,进行具体分析:

发现都是网络超时,这跟网络情况相关,或者我的服务器稳定性比较差~

TIP:

JMeter从CSV读取数据并不只适用于数据存放在URL参数里面。

  1. 不仅限于URL参数:虽然CSV数据常用于URL参数化,但JMeter也支持将CSV中的数据用于其他类型的请求参数,如POST请求的body、请求头等。

我们现在做的就是将数据存放在body中。

3.4.自动化测试

3.4.1.测试框架:

在common这个软件包中主要存放的是utils这个工具类,这个工具类里面具体实现了创建浏览器对象和截图工具,避免每次测试都需要写一份工具,避免了代码的冗余。

在images这个文件夹中存放的是每次截图生成的图片,并且以天为单位生成小的文件夹,每份文件夹又有用时间进行格式化和生成该图片的类名。

在tests这个软件包中存放的是各个页面的自动化测试代码,并且RunTest文件进行总体的一个测试。

3.4.2.utils工具类的实现
代码语言:javascript
代码运行次数:0
复制
import os
import sys
import datetime

from selenium import webdriver
from selenium.webdriver.ie.service import Service
from webdriver_manager.chrome import ChromeDriverManager


#创建一个浏览器对象

class Driver:
    driver = ""
    def __init__(self):
        options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=options)

    def getScreeShot(self):
        # 创建屏幕截图
        # 图片文件名称:./2024-05-08-173456.png
        dirname = datetime.datetime.now().strftime("%Y-%m-%d")

        # 判断dirname文件夹是否已经存在,若不存在则创建文件夹
        # ../images/2024-05-08
        if not os.path.exists("../images/" + dirname):
            os.mkdir("../images/" + dirname)
        # 2024-05-08-173456.png
        # 图片路径:../images/调用方法-2024-05-08/2024-05-08-173456.png
        # 图片路径:../images/LoginSucTest-2024-05-08/2024-05-08-173456.png
        # 图片路径:../images/LoginFailTest-2024-05-08/2024-05-08-173456.png
        filename = sys._getframe().f_back.f_code.co_name + "-" + datetime.datetime.now().strftime(
            "%Y-%m-%d-%H%M%S") + ".png"
        self.driver.save_screenshot("../images/" + dirname + "/" + filename)
BlogDriver = Driver()

其中截图的工具类别出心裁:

  1. sys._getframe().f_back.f_code.co_name 通过调用栈获取调用该代码的函数名,作为文件名的一部分。这样可以动态地根据函数名为截图命名。
  2. datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S") 获取当前时间,并将其格式化为“年-月-日-时分秒”的形式,作为文件名中的时间戳部分。
  3. filename 将函数名和时间戳拼接成一个完整的文件名,后缀为“.png”。
  4. self.driver.save_screenshot("../images/" + dirname + "/" + filename) 使用 Selenium 的 save_screenshot 方法,将当前浏览器窗口的截图保存到指定路径中。路径由 ../images/dirname(某个子目录名)以及生成的文件名组成。
3.4.3.注册界面自动化测试

代码:

代码语言:javascript
代码运行次数:0
复制
#测试注册界面
import time
from distutils.command.register import register

from selenium.webdriver.common.by import By

from common.Utils import BlogDriver


class GobangRegister:
    url = ""
    driver = ""
    def __init__(self):
        self.url = "http://123.249.125.60:8085/register.html"
        self.driver = BlogDriver.driver
        self.driver.get(self.url)
    #成功注册的测试用例
    def RegisterSucTest(self):
        self.driver.find_element(By.CSS_SELECTOR,"#user_name").send_keys("lisi9")
        self.driver.find_element(By.CSS_SELECTOR,"#password").send_keys("123456")
        self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
        #强制等待
        time.sleep(3)
        #此时需要点击弹窗里面的确定,才能跳转页面
        alert = self.driver.switch_to.alert
        alert.accept()
        #能够找到登录界面中的登录二字,说明注册成功,否则注册失败
        self.driver.find_element(By.CSS_SELECTOR,"body > div.login-container > div > h3")
    #异常注册的测试用例
    def RegisterFailTest(self):
        #若连续多次的send_keys会出现关键词的拼接,而不是替换。若要替换需要先clear
        self.driver.find_element(By.CSS_SELECTOR,"#user_name").clear()
        self.driver.find_element(By.CSS_SELECTOR,"#password").clear()
        self.driver.find_element(By.CSS_SELECTOR,"#user_name").send_keys("lisi")
        self.driver.find_element(By.CSS_SELECTOR,"#password").send_keys("123456")
        self.driver.find_element(By.CSS_SELECTOR,"#submit").click()
        time.sleep(3)
        #self.driver.quit()

_register = GobangRegister()
_register.RegisterSucTest()
#_register.RegisterFailTest()
3.4.4.登录界面自动化测试
代码语言:javascript
代码运行次数:0
复制
#测试登录页面
import time

from common.Utils import BlogDriver
from selenium.webdriver.common.by import By


class GobangLogin:
    url = ''
    driver = ''
    def __init__(self):
        self.url = "http://123.249.125.60:8085/login.html"
        self.driver = BlogDriver.driver
        self.driver.get(self.url)

    #登录失败的测试用例
    def LoginFailTest(self):
        #隐式等待
        #self.driver.implicitly_wait(3)
        self.driver.find_element(By.CSS_SELECTOR,'#user_name').send_keys('lisi8')
        self.driver.find_element(By.CSS_SELECTOR,'#password').send_keys('123456')
        self.driver.find_element(By.CSS_SELECTOR,'#submit').click()
        time.sleep(3)
        #此时需要点击弹窗里面的确定,才能跳转页面
        alert = self.driver.switch_to.alert
        alert.accept()
        time.sleep(3)

    #成功登录的测试用例
    def LoginSucTest(self):
        self.driver.find_element(By.CSS_SELECTOR,'#user_name').send_keys('lisi')
        self.driver.find_element(By.CSS_SELECTOR,'#password').send_keys('123456')
        self.driver.find_element(By.CSS_SELECTOR,'#submit').click()

        time.sleep(3)
        #此时需要点击弹窗里面的确定,才能跳转页面
        alert = self.driver.switch_to.alert
        alert.accept()
        time.sleep(3)

        # self.driver.find_element(By.CSS_SELECTOR,'#match-button')
        # #截图
        # BlogDriver.getScreeShot()
        # #self.driver.quit()
        # #强制等待
        # time.sleep(3)
        # #此时需要点击弹窗里面的确定,才能跳转页面
        # alert = self.driver.switch_to.alert
        # alert.accept()
        # time.sleep(3)
        #time.sleep(3)
        #此时需要点击弹窗里面的确定,才能跳转页面
        alert = self.driver.switch_to.alert
        alert.accept()
        time.sleep(3)

# _login = GobangLogin()
# # _login.LoginFailTest()
# _login.LoginSucTest()
3.4.5.游戏大厅界面自动化测试
代码语言:javascript
代码运行次数:0
复制
#测试游戏大厅页面
import time

from common.Utils import BlogDriver
from selenium.webdriver.common.by import By

class GobangHall:
    url = ' '
    driver = ' '
    def __init__(self):
        self.url = "http://123.249.125.60:8085/game_hall.html"
        self.driver = BlogDriver.driver
        self.driver.get(self.url)
    #测试游戏大厅匹配和停止匹配按钮
    def HallTest(self):
        time.sleep(3)
        #此时需要点击弹窗里面的确定,才能跳转页面
        alert = self.driver.switch_to.alert
        alert.accept()
        #点击开始匹配
        self.driver.find_element(By.CSS_SELECTOR,'#match-button').click()
        #点击停止匹配
        self.driver.find_element(By.CSS_SELECTOR,'#match-button').click()
        time.sleep(3)
        #重新匹配
        self.driver.find_element(By.CSS_SELECTOR,'#match-button').click()
        #截图
        BlogDriver.getScreeShot()
3.4.6.集成测试:
代码语言:javascript
代码运行次数:0
复制
#from tests import GobangRegister
from tests import GobangLogin
from tests import GobangHall
from common.Utils import BlogDriver

if __name__ == "__main__":
    #游戏注册页面
    #GobangRegister.GobangRegister().RegisterSucTest()
    #GobangLogin.GobangLogin().LoginFailTest()
    #登陆成功之后就可以调用博客首页测试首页的用例(登陆状态)
    #最终一定是登录状态
    GobangLogin.GobangLogin().LoginSucTest()
    #游戏大厅界面
    GobangHall.GobangHall().HallTest()
    #指定浏览器的退出
    BlogDriver.driver.quit()
3.4.7.测试总结:

如上图运行过程所示,我们的自动化测试用例全部通过,当我们执行失败的时候需要截图进行纠错。

自动化测试盲点难点解决方法:

1.注意弹窗只能是用强制等待或者是显示等待!、

为什么?

在Selenium自动化测试中,当遇到弹窗时,通常使用的等待方式主要是显式等待。这是因为弹窗的出现往往是由某些用户操作或页面事件触发的,而这些事件可能不是立即发生的,因此需要等待弹窗确实出现后再进行相应的操作。

注意在前面文件中不需要我们自己退出,我们只用在最后的RunTest一次退出即可,不然前面程序已经退出,将会运行失败

2.隐式等待为什么要写在utils文件中,不能写在后面的文件里面吗

解答:

#点击完成之后出现页面的跳转,页面跳转需要加载时间,可能会出现代码执行的速度比页面渲染的速度要快,导致元素查找不到,因此可以添加等待

#添加隐式等待和显示等待都可以,任选择一个

#隐式等待:创建浏览器对象之后就可以加上,因为隐式等待的作用域在driver整个生命周期

#显示等待:可以作用在当前代码中

四.总结:

我们一共进行了功能测试、自动化测试以及性能测试这三种测试方式,在功能测试阶段,我们着重点是测试玩家双方进行五子棋对弈时的过程;在自动化测试阶段,我们主要测试各个页面的相关信息,着重测试了登录与注册的功能;在性能测试阶段,我们着重测试了用户登录与获取用户信息的接口性能,并生成了性能测试报告。

在这期间,发现了不少bug,例如用户注册时,没有账号和密码也能注册成功;当用户的名称过长时,会对前端界面按钮造成覆盖等等。但最终都解决了,不得不说,测试真的很有意思~~~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、项目背景
    • 1.1、项目起源
    • 1.2、市场需求
    • 1.3、项目目标
  • 二、项目功能
    • 2.1 用户管理功能
    • 2.2 游戏对战功能
  • 三、测试报告
    • 3.1.功能测试
      • 3.1.1注册功能测试
      • 解决bug:
      • 测试总结:
      • 3.1.2登录功能测试
      • 测试总结:
      • 3.1.3.匹配和落子测试
    • 3.2.界面测试
    • bug:
      • 测试总结
    • 3.3.性能测试
      • 总体测试框架:
      • 3.3.1.利用BeanShell解决乱码问题
      • 3.3.2.添加保存cookie信息
      • 3.3.3.添加CSV格式的用户信息
      • 3.3.4.添加同步定时器
      • 3.3.5.创建梯度压测线程组
      • 3.3.6.生成测试报告
    • TIP:
    • 3.4.自动化测试
      • 3.4.1.测试框架:
      • 3.4.2.utils工具类的实现
      • 3.4.3.注册界面自动化测试
      • 3.4.4.登录界面自动化测试
      • 3.4.5.游戏大厅界面自动化测试
      • 3.4.6.集成测试:
      • 3.4.7.测试总结:
    • 自动化测试盲点难点解决方法:
      • 1.注意弹窗只能是用强制等待或者是显示等待!、
      • 2.隐式等待为什么要写在utils文件中,不能写在后面的文件里面吗
  • 四.总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档