一、项目背景

本项目为仿QQ音乐在线音乐平台,采用Vue + HTML + CSS + JavaScript 开发,基于前后端分离架构实现。完成歌曲播放、歌词同步、搜索、歌单管理、播放控制、首页推荐等核心功能,界面与交互高度还原官方产品。通过接口请求、组件化开发、音频控制等技术,实现完整业务流程,提升了前端工程化与项目实战能力。

二、项目功能

1.播放与暂停功能:当你点击进入仿QQ音乐项目时,你会发现中心底部它会有个三角形,你进行点击会播放你所选中的音乐,再点击一次,音乐就会暂停

2.随机播放:当你点击随机播放时,你当前的这首歌播放完后,会随机跳到下一首歌曲,但是不一定是按顺序播放,它可能跳到第三首或者第四首。单曲循环:当你点击单曲循环时,你点击一首歌曲,歌曲播放完后,它下次播放的还是当前这首歌曲。顺序播放:当你点击顺序循环时,你点击一首歌曲,歌曲播放完后,它下次播放的是按顺序的第二首歌曲

3.音量调节大小:点击音量,调节声音大小

4.导入歌曲:点击"+"号将我们需要的音乐导入进去,才能进行播放

5.播放全部:点击播放全部,它会从第一首歌曲开始播放

6.最小化:点击"-"号,会将画面隐藏起来

7.添加/删除 喜欢:点击歌曲前面的爱心按钮,歌曲会被添加进我喜欢里面,再次点击爱心按钮,我喜欢里面会去除这首歌曲

8.上一曲/下一曲:点击|<|按钮歌曲会回到上一首歌曲,点击|>|按钮歌曲会跳转到下一首歌曲

7.搜索:搜索框能输入文字

三、测试目的

1.功能验证

  • 确保核心功能实现,如暂停与播放能正常使用
  • 需要的歌曲能正常导入进去,实现播放
  • 播放模式:随机播放/单曲循环/顺序播放能正常使用

2.用户体验

  • 评估界面布局的合理性和易用性
  • 检查页面上的按钮是否能正常使用

四、测试用例

五、自动化测试

创建一个tests,分别创建test_command.py、test_like.py、test_local.py、test_recommend.py、test_songwords.py五个模块测试不同页面的功能

公共模块:测试logo、测试搜索功能、测试换皮肤功能、测试最小化、测试导入音乐、测试随机播放、测试单曲循环、测试顺序循环

公共模块

测试logo:界面正常打开,测试通过

 # 测试logo
    def test_log(self,QQMusic_app):
        logo_ele=read_yaml("logo")
        logo=QQMusic_app.win.child_window(auto_id=logo_ele['auto_id'], control_type=logo_ele['control_type'])
        logo.wait("visible")

测试搜索功能:界面打开,搜索框输入"周杰伦",测试通过

# 测试搜索功能
    def test_search(self,QQMusic_app):
        edit_ele=read_yaml("search")
        edit=QQMusic_app.win.child_window(auto_id=edit_ele['auto_id'], control_type=edit_ele['control_type'])
        # 唤起输入框
        edit.click_input()
        # ctrl+a全部选中之后再输入关键词,就不会存在追加情况
        edit.type_keys("^a周杰伦")

测试换皮肤功能:点击换皮肤,出现文本,测试通过

# 测试换皮肤功能
    def test_skin(self,QQMusic_app):
        skin_ele=read_yaml("换肤")
        skin=QQMusic_app.win.child_window(auto_id=skin_ele['auto_id'], control_type=skin_ele['control_type'])
        # 点击换皮肤入口,唤起弹窗
        skin.click_input()

        # 验证弹窗以及文本信息
        warning=QQMusic_app.win.child_window(title="温馨提示",control_type="Window")
        warning.wait("visible")
        warn_text=warning.child_window(control_type="Text").window_text()
        assert warn_text=="换肤功能小哥哥正在紧急支持中..."

        # 关闭温馨提示弹窗
        warning.close()
        # 测试弹窗是否正确关闭
        warning.wait_not("visible")

测试最小化:进入页面最下化,页面隐藏,测试通过

# 测试最小化
    def test_window_min(self,QQMusic_app):
        window_min_ele=read_yaml("最小化")
        window_min_btn=QQMusic_app.win.child_window(auto_id= window_min_ele['auto_id'],
                                                    control_type= window_min_ele['control_type'])
        # 点击最小化按钮
        window_min_btn.click_input()
        # 测试一下QQ音乐窗口是否已经最小化了
        assert QQMusic_app.win.is_minimized()
        # 还原
        QQMusic_app.win.restore()

测试导入音乐:进入页面,点击"+"按钮导入歌曲,测试通过

#测试导入音乐
    def test_importMusic(self,QQMusic_app):
        import_ele=read_yaml("导入音乐")
        import_btn=QQMusic_app.win.child_window(auto_id= import_ele['auto_id'],
                                                    control_type= import_ele['control_type'])
        # 点击导入音乐按钮
        import_btn.click_input()

        #定位添加本地下载音乐窗口
        import_win=QQMusic_app.win.child_window(title="添加本地下载音乐",control_type="Window")
        import_win.wait("visible")

        # 选中所有音乐添加
        music_list=import_win.child_window(title="项目视图",control_type="List")
        # 打开音乐:1)通过按钮实现2)enter实现
        music_list.type_keys("^a{ENTER}")

        import_win.wait_not("visible")

测试随机播放:随机播放三首歌曲,三首歌曲不一样,测试通过

#测试随机播放
def test_play_random(self, QQMusic_app):
        # 点击播放全部
        local_ele = read_yaml("本地下载")
        play_all_ele = local_ele["播放全部"]
        play_btn = QQMusic_app.win.child_window(auto_id=play_all_ele['auto_id'],
                                                control_type=play_all_ele['control_type'])

        for i in range(1, 4):
            # 点击播放全部,从第一首歌曲开始播放(2002年的第一场雪)
            play_btn.click_input()
            # 将歌曲播放进度拉到尾部

            play_ele = read_yaml("播放控制")
            process_line_ele = play_ele["播放总进度"]
            process_line = QQMusic_app.win.child_window(auto_id=process_line_ele['auto_id'],
                                                        control_type=process_line_ele['control_type'])
            # 获取进度条的尺寸
            rec = process_line.rectangle()
            x = rec.right - 3
            y = math.floor((rec.top + rec.bottom) / 2)

            # 鼠标点击进度条的尾部
            mouse.click(coords=(x, y))

            # 等待切换下一曲
            time.sleep(2)
            # 检查下一步是否为列表中第二首歌曲
            #             1)若是,随机播放模式不一定错误
            #             2)若不是,随机播放模式正确
            music_name_ele = play_ele["歌曲名"]
            music_name = QQMusic_app.win.child_window(auto_id=music_name_ele['auto_id'],
                                                      control_type=music_name_ele['control_type']).window_text()
            if music_name != "Andy阿杜":
                self.logger.info(f"第{i}次判断随机播放下一曲正确")
                return
            else:
                self.logger.info(f"第{i}次判断随机播放下一曲错误")
        # 走到这里还没有返回
        raise Exception("随机播放下一曲三次判断均错误")

测试单曲循环:播放一首歌曲,歌曲播放完后,播放原来歌曲,测试通过

#测试单曲循环 
def test_play_single(self, QQMusic_app):
        # 点击播放全部
        local_ele = read_yaml("本地下载")
        play_all_ele = local_ele["播放全部"]
        play_btn = QQMusic_app.win.child_window(auto_id=play_all_ele['auto_id'],
                                                control_type=play_all_ele['control_type'])
        # 切换模式:随机播放——单曲循环
        play_ele = read_yaml("播放控制")
        playMode_ele = play_ele["模式切换"]
        playMode_btn = QQMusic_app.win.child_window(auto_id=playMode_ele['auto_id'],
                                                    control_type=playMode_ele['control_type'])
        # 点击切换模式按钮
        playMode_btn.click_input()

        for i in range(1, 4):
            # 点击播放全部按钮
            play_btn.click_input()

            music_name_ele = play_ele["歌曲名"]
            music_name_before = QQMusic_app.win.child_window(auto_id=music_name_ele['auto_id'],
                                                             control_type=music_name_ele['control_type']).window_text()

            # 将歌曲播放进度拉到尾部
            process_line_ele = play_ele["播放总进度"]
            process_line = QQMusic_app.win.child_window(auto_id=process_line_ele['auto_id'],
                                                        control_type=process_line_ele['control_type'])
            # 获取进度条的尺寸
            rec = process_line.rectangle()
            x = rec.right - 3
            y = math.floor((rec.top + rec.bottom) / 2)

            # 鼠标点击进度条的尾部
            mouse.click(coords=(x, y))

            # 等待切换下一曲
            time.sleep(2)
            # 下一首播放的歌曲和前一首歌曲是否相同
            #        1)相同,单曲循环模式不一定正确---多次验证
            #        2)不相同,单曲循环模式错误
            music_name_after = QQMusic_app.win.child_window(auto_id=music_name_ele['auto_id'],
                                                            control_type=music_name_ele['control_type']).window_text()
            if music_name_before != music_name_after:
                self.logger.error(
                    f"单曲循环模式播放下一首歌曲校验错误,before:{music_name_before},after:{music_name_after}")
                break
            else:
                self.logger.info(f"第{i}次校验单曲循环模式播放下一首歌曲正确")
                if i == 3:
                    return
        raise Exception(f"单曲循环模式播放下一首歌曲校验错误,before:{music_name_before},after:{music_name_after}")

测试列表循环:下拉至最后一首歌曲,拖动进度,播放第一曲,测试通过

#测试列表循环
def test_play_circle(self, QQMusic_app):
        # 切换模式:单曲循环——列表循环
        play_ele = read_yaml("播放控制")
        music_name_ele = play_ele["歌曲名"]
        playMode_ele = play_ele["模式切换"]
        playMode_btn = QQMusic_app.win.child_window(auto_id=playMode_ele['auto_id'],
                                                    control_type=playMode_ele['control_type'])
        # 点击切换模式按钮
        playMode_btn.click_input()

        for i in range(1, 4):
            # 找到列表中最后一首歌曲
            music_list_ele = read_yaml("歌曲列表")
            music_list = QQMusic_app.win.child_window(auto_id=music_list_ele['auto_id'],
                                                      control_type=music_list_ele['control_type'])
            # 获取歌曲列表的中间坐标
            list_mid = music_list.rectangle().mid_point()
            # 鼠标下拉列表使其展示最后一首歌曲
            mouse.scroll(coords=(list_mid.x, list_mid.y), wheel_dist=-500)
            # 获取最后一首歌曲——求列表中列表项目数
            list_size = music_list.item_count()
            # 双击最后一首歌曲,使其播放
            last_music_mid = music_list.get_item(row=list_size - 1).rectangle().mid_point()
            mouse.double_click(coords=(last_music_mid.x, last_music_mid.y))

            # 拉取进度条到尾部,等待播放下一曲
            process_line_ele = play_ele["播放总进度"]
            process_line = QQMusic_app.win.child_window(auto_id=process_line_ele['auto_id'],
                                                        control_type=process_line_ele['control_type'])
            # 获取进度条的尺寸
            rec = process_line.rectangle()
            x = rec.right - 3
            y = math.floor((rec.top + rec.bottom) / 2)

            # 鼠标点击进度条的尾部
            mouse.click(coords=(x, y))

            # 等待切换下一曲
            time.sleep(2)
            # 校验播放的下一首歌曲是否为“2002年的第一场雪(列表的第一首歌曲)”
            #            1)是,列表循环校验不一定正确
            #            2)不是,列表循环校验错误
            music_name = QQMusic_app.win.child_window(auto_id=music_name_ele['auto_id'],
                                                      control_type=music_name_ele['control_type']).window_text()
            if music_name != "2002年的第一场雪":
                self.logger.error(f"列表循环下一曲错误,music_name:{music_name}")
                break
            else:
                self.logger.info(f"第{i}次校验列表循环下一曲正确")
                if i == 3:
                    return
        raise Exception(f"列表循环下一曲错误,music_name:{music_name}")

我喜欢

我喜欢模块:测试我喜欢文本、测试我喜欢播放全部、测试我喜欢模块-标记喜欢、测试我喜欢模块—选择歌曲双击播放、

测试我喜欢文本

def test_like_text(self,QQMusic_app):
        like_ele = read_yaml("我喜欢")
        #点击导航栏“我喜欢”进入到我喜欢模块
        like_btn = QQMusic_app.win.child_window(auto_id=like_ele["auto_id"],
                                     control_type=like_ele["control_type"])
        like_btn.click_input()
        #测试“我喜欢”文本
        like_text_ele = like_ele["我喜欢文本"]
        like_text = QQMusic_app.win.child_window(auto_id=like_text_ele["auto_id"],
                                     control_type=like_text_ele["control_type"]).window_text()
        assert like_text == "我喜欢"

        #测试“歌曲名称”文本
        songname_text_ele = like_ele["歌曲名称文本"]
        songname_text = QQMusic_app.win.child_window(auto_id=songname_text_ele["auto_id"],
                                     control_type=songname_text_ele["control_type"]).window_text()
        assert songname_text == "歌曲名称"

        #测试“歌手名称”文本
        singername_text_ele = like_ele["歌手名称文本"]
        singername_text = QQMusic_app.win.child_window(auto_id=singername_text_ele["auto_id"],
                                                     control_type=singername_text_ele["control_type"]).window_text()
        assert singername_text == "歌手名称"

        #测试“专辑名称”文本
        albumrname_text_ele = like_ele["专辑名称文本"]
        albumrname_text = QQMusic_app.win.child_window(auto_id=albumrname_text_ele["auto_id"],
                                                       control_type=albumrname_text_ele["control_type"]).window_text()
        assert albumrname_text == "专辑名称"

测试我喜欢播放全部

 '''
 我喜欢模块——播放全部
 '''
    def test_like_playAll(self,QQMusic_app):
        playAll_ele = read_yaml("我喜欢")["播放全部"]
        playAll_btn = QQMusic_app.win.child_window(auto_id=playAll_ele["auto_id"],
                                                       control_type=playAll_ele["control_type"])
        #点击播放全部按钮
        playAll_btn.click_input()
        #获取播放进度
        process_line_ele = read_yaml("播放控制")["当前播放进度"]
        process_line_before = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                       control_type=process_line_ele["control_type"])
        process_line_len_before = process_line_before.rectangle().right
        #等待两秒
        time.sleep(2)
        #获取播放进度
        process_line_after = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                           control_type=process_line_ele["control_type"])
        process_line_len_after = process_line_after.rectangle().right
        #比较前后两次进度变化,有变化则说明按钮没有问题
        assert process_line_len_before != process_line_len_after

测试我喜欢模块-标记喜欢


    '''
    我喜欢模块——测试标记喜欢
    '''
    def test_mark_unLike(self,QQMusic_app):
        #获取歌曲列表中歌曲的数量
        music_list_ele = read_yaml("我喜欢")["歌曲列表"]
        music_list_before = QQMusic_app.win.child_window(auto_id=music_list_ele["auto_id"],
                                                  control_type=music_list_ele["control_type"])
        # 获取歌曲列表歌曲数量
        list_size_before = music_list_before.item_count()
        #取消标记喜欢
        rec = music_list_before.get_item(row=0).rectangle()
        y = math.floor((rec.top + rec.bottom)/2)
        x = rec.left + 22
        mouse.click(coords=(x,y))
        #获取歌曲列表中歌曲的数量
        music_list_after = QQMusic_app.win.child_window(auto_id=music_list_ele["auto_id"],
                                                         control_type=music_list_ele["control_type"])
        # 获取歌曲列表歌曲数量
        list_size_after = music_list_after.item_count()
        #测试取消标记喜欢是否成功
        assert list_size_after + 1 == list_size_before

测试我喜欢模块—选择歌曲双击播放


    '''
    我喜欢模块——选择歌曲双击播放
    '''
    def test_like_playSingle(self,QQMusic_app):
        music_list_ele = read_yaml("我喜欢")["歌曲列表"]
        music_list = QQMusic_app.win.child_window(auto_id=music_list_ele["auto_id"],
                                     control_type=music_list_ele["control_type"])
        #获取歌曲列表歌曲数量
        list_size = music_list.item_count()
        if list_size <= 0:
            assert 0,"歌曲列表为空"
        #选择第一首歌曲双击播放
        point = music_list.get_item(row=0).rectangle().mid_point()
        mouse.double_click(coords=(point.x,point.y))
        # 获取播放进度
        process_line_ele = read_yaml("播放控制")["当前播放进度"]
        process_line_before = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                           control_type=process_line_ele["control_type"])
        process_line_len_before = process_line_before.rectangle().right
        # 等待两秒
        time.sleep(2)
        # 获取播放进度
        process_line_after = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                          control_type=process_line_ele["control_type"])
        process_line_len_after = process_line_after.rectangle().right
        # 比较前后两次进度变化,有变化则说明双击歌曲播放没有问题
        assert process_line_len_before != process_line_len_after

本地下载

本地下载模块:测试本地下载模块—文本、测试本地下载播放全部功能、测试本地下载模块选择歌曲并双击播放、测试将歌曲标记喜欢

测试本地下载模块—文本


    # '''
    # 测试本地下载模块——文本
    # “本地音乐、歌曲名称、歌手名称、专辑名称”
    # '''
    def test_local_text(self,QQMusic_app):
        local_ele = read_yaml("本地下载")
        #点击导航栏-本地下载,进入本地下载页面
        local = QQMusic_app.win.child_window(auto_id=local_ele["auto_id"],
                                             control_type=local_ele["control_type"])
        local.click_input()
        #测试“本地音乐文本"
        local_text_ele = local_ele["本地音乐文本"]
        local_text = QQMusic_app.win.child_window(auto_id=local_text_ele["auto_id"],
                                             control_type=local_text_ele["control_type"]).window_text()
        assert local_text == "本地音乐"

        #测试“歌曲名称文本"
        songname_text_ele = local_ele["歌曲名称文本"]
        songname_text = QQMusic_app.win.child_window(auto_id=songname_text_ele["auto_id"],
                                             control_type=songname_text_ele["control_type"]).window_text()
        print(songname_text)
        assert songname_text == "歌曲名称"

        #测试“歌手名称文本"
        singername_text_ele = local_ele["歌手名称文本"]
        singername_text = QQMusic_app.win.child_window(auto_id=singername_text_ele["auto_id"],
                                                     control_type=singername_text_ele["control_type"]).window_text()
        assert singername_text == "歌手名称"

   

测试本地下载播放全部功能

    '''
    测试本地下载模块——播放全部功能
    '''
    def test_local_playAll(self,QQMusic_app):
        local_ele = read_yaml("本地下载")
        playAll_ele = local_ele["播放全部"]
        playAll_btn = QQMusic_app.win.child_window(auto_id=playAll_ele["auto_id"],
                                                       control_type=playAll_ele["control_type"])
        #点击播放全部按钮
        playAll_btn.click_input()
        #获取播放进度
        process_line_ele = read_yaml("播放控制")["当前播放进度"]
        process_line_before = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                       control_type=process_line_ele["control_type"])
        process_line_len_before = process_line_before.rectangle().right
        #等待两秒
        time.sleep(2)
        #获取播放进度
        process_line_after = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                    control_type=process_line_ele["control_type"])
        process_line_len_after = process_line_after.rectangle().right
        #测试前后两个进度是否存在差别
        assert process_line_len_before != process_line_len_after

  

测试本地下载模块——选择歌曲并双击播放

  '''
  测试本地下载模块——选择歌曲并双击播放
  '''
    def test_local_playSingle(self,QQMusic_app):
        music_list_ele = read_yaml("歌曲列表")
        music_list = QQMusic_app.win.child_window(auto_id=music_list_ele["auto_id"],
                                                    control_type=music_list_ele["control_type"])
        #将歌曲列表还原到最上方——————公共模块测试循环播放找最后一首歌曲将列表拉到了最下面
        point = music_list.rectangle().mid_point()
        mouse.scroll(coords=(point.x,point.y),wheel_dist=500)
        #获取歌曲列表中歌曲数量
        if music_list.item_count() <= 0:
            assert 0,"歌曲列表为空"
        #选择一首歌曲并双击播放
        point = music_list.get_item(row=0).rectangle().mid_point()
        mouse.double_click(coords=(point.x,point.y))
        # 获取播放进度
        process_line_ele = read_yaml("播放控制")["当前播放进度"]
        process_line_before = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                           control_type=process_line_ele["control_type"])
        process_line_len_before = process_line_before.rectangle().right
        # 等待两秒
        time.sleep(2)
        # 获取播放进度
        process_line_after = QQMusic_app.win.child_window(auto_id=process_line_ele["auto_id"],
                                                          control_type=process_line_ele["control_type"])
        process_line_len_after = process_line_after.rectangle().right
        # 测试前后两个进度是否存在差别
        assert process_line_len_before != process_line_len_after

测试将歌曲标记喜欢

    '''
    将歌曲标记喜欢——为了后面我喜欢模块的测试提供数据
    '''
    def test_mark_like(self,QQMusic_app):
        #获取歌曲列表中歌曲数量
        music_list_ele = read_yaml("歌曲列表")
        music_list = QQMusic_app.win.child_window(auto_id=music_list_ele["auto_id"],
                                                  control_type=music_list_ele["control_type"])
        list_size = music_list.item_count()
        #对每一首歌曲标记喜欢
        for i in range(0,list_size):
            if i != 0 and i % 6 == 0:
                #6及以后的歌曲在标记喜欢之前需要先向下滑动,使其显示出来
                point = music_list.rectangle().mid_point()
                mouse.scroll(coords=(point.x,point.y),wheel_dist=-500)
            rec = music_list.get_item(row=i).rectangle()
            #获取爱心的中间位置(x,y)
            y = math.floor((rec.top + rec.bottom)/2)
            x = rec.left + 22
            mouse.click(coords=(x,y))

推荐页面

推荐模块:测试—推荐页面的文本、测试今日为你推荐滚动区域——左滚动、测试今日为你推荐滚动区域—右滚动、测试你的音乐补给滚动区域—左滚动、测试你的音乐补给滚动区域—右滚动

测试—推荐页面的文本
推荐、今日为你推荐、你的音乐补给

  '''
  测试——推荐页面的文本
  "推荐、今日为你推荐、你的音乐补给"
  '''
    def test_rec_text(self,QQMusic_app):
        #点击左侧的推荐导航入口,进入到推荐页面
        rec_ele = read_yaml("推荐")
        rec_btn = QQMusic_app.win.child_window(auto_id=rec_ele["auto_id"],
                                           control_type=rec_ele["control_type"])
        rec_btn.click_input()
        #获取“推荐”文本控件
        rec_text_ele = rec_ele["推荐文本"]
        #获取“今日为你推荐”文本控件
        rec_foru_text_ele = rec_ele["今日为你推荐文本"]
        #获取“你的音乐补给”文本控件
        rec_supply_text_ele = rec_ele["你的音乐补给文本"]

        #校验“推荐”文本控件
        rec_text =  QQMusic_app.win.child_window(auto_id=rec_text_ele["auto_id"],
                                           control_type=rec_text_ele["control_type"])
        assert rec_text.window_text() == "推荐"

        # 校验“今日为你推荐”文本控件
        rec_foru_text = QQMusic_app.win.child_window(auto_id=rec_foru_text_ele["auto_id"],
                                           control_type=rec_foru_text_ele["control_type"])
        assert rec_foru_text.window_text() == "今日为你推荐"

        #校验“你的音乐补给”文本控件
        rec_supply_text = QQMusic_app.win.child_window(auto_id=rec_supply_text_ele["auto_id"],
                                           control_type=rec_supply_text_ele["control_type"])
        assert rec_supply_text.window_text() == "你的音乐补给"

测试今日为你推荐滚动区域——左滚动

'''
测试今日为你推荐滚动区域——左滚动
'''
    def test_recforu_scroll_left(self,QQMusic_app):
        rec_ele = read_yaml("推荐")

        item_text_ele = rec_ele["今日为你推荐第一项文本"]
        item_text_before = QQMusic_app.win.child_window(auto_id=item_text_ele["auto_id"],
                                           control_type=item_text_ele["control_type"],
                                            found_index=0).window_text()

        scroll_left_ele = rec_ele["今日为你推荐左滚动"]
        scroll_left = QQMusic_app.win.child_window(auto_id=scroll_left_ele["auto_id"],
                                           control_type=scroll_left_ele["control_type"])
        #点击左滚动按钮
        scroll_left.click_input()
        #获取推荐项的名称,进行前后对比校验
        item_text_after = QQMusic_app.win.child_window(auto_id=item_text_ele["auto_id"],
                                           control_type=item_text_ele["control_type"],
                                            found_index=0).window_text()

        assert item_text_before != item_text_after


测试今日为你推荐滚动区域—右滚动

'''
测试今日为你推荐滚动区域——右滚动
'''

    def test_recforu_scroll_right(self, QQMusic_app):
        rec_ele = read_yaml("推荐")

        item_text_ele = rec_ele["今日为你推荐第一项文本"]
        item_text_before = QQMusic_app.win.child_window(auto_id=item_text_ele["auto_id"],
                                                        control_type=item_text_ele["control_type"],
                                                        found_index=0).window_text()

        scroll_right_ele = rec_ele["今日为你推荐右滚动"]
        scroll_right = QQMusic_app.win.child_window(auto_id=scroll_right_ele["auto_id"],
                                                   control_type=scroll_right_ele["control_type"])
        # 点击右滚动按钮
        scroll_right.click_input()
        # 获取推荐项的名称,进行前后对比校验
        item_text_after = QQMusic_app.win.child_window(auto_id=item_text_ele["auto_id"],
                                                       control_type=item_text_ele["control_type"],
                                                       found_index=0).window_text()

        assert item_text_before != item_text_after


  

测试你的音乐补给滚动区域—左滚动

'''
测试——你的音乐补给滚动区域——左滚动
'''
    def test_supply_scroll_left(self,QQMusic_app):
        rec_ele = read_yaml("推荐")
        all_rec_area_ele = rec_ele["推荐整个模块"]
        all_rec_area = QQMusic_app.win.child_window(auto_id=all_rec_area_ele["auto_id"],
                                     control_type=all_rec_area_ele["control_type"])
        #找推荐整个模块的中间坐标
        point = all_rec_area.rectangle().mid_point()
        #在推荐模块鼠标下拉,展示完整的为你推荐区域
        mouse.scroll(coords=(point.x,point.y),wheel_dist=-500)
        #点击左滚动按钮
        scroll_left_ele = rec_ele["音乐补给左滚动"]
        one_one_ele = rec_ele["音乐补给第一排第一项文本"]
        two_one_ele = rec_ele["音乐补给第二排第一项文本"]

        one_one_text_before = QQMusic_app.win.child_window(auto_id=one_one_ele["auto_id"],
                                                       control_type=one_one_ele["control_type"],
                                                    found_index=0).window_text()
        two_one_text_before = QQMusic_app.win.child_window(auto_id=two_one_ele["auto_id"],
                                                       control_type=two_one_ele["control_type"],
                                                    found_index=0).window_text()

        scroll_left_btn = QQMusic_app.win.child_window(auto_id=scroll_left_ele["auto_id"],
                                     control_type=scroll_left_ele["control_type"])
        scroll_left_btn.click_input()
        #左滚动结果的校验--项目名称是否变化
        one_one_text_after = QQMusic_app.win.child_window(auto_id=one_one_ele["auto_id"],
                                                           control_type=one_one_ele["control_type"],
                                                           found_index=0).window_text()
        two_one_text_after = QQMusic_app.win.child_window(auto_id=two_one_ele["auto_id"],
                                                           control_type=two_one_ele["control_type"],
                                                           found_index=0).window_text()
        assert one_one_text_after != one_one_text_before
        assert two_one_text_after != two_one_text_before



 

测试你的音乐补给滚动区域—右滚动

'''
测试——你的音乐补给滚动区域——右滚动
'''

    def test_supply_scroll_right(self, QQMusic_app):
        rec_ele = read_yaml("推荐")
        all_rec_area_ele = rec_ele["推荐整个模块"]
        all_rec_area = QQMusic_app.win.child_window(auto_id=all_rec_area_ele["auto_id"],
                                                    control_type=all_rec_area_ele["control_type"])
        # 找推荐整个模块的中间坐标
        point = all_rec_area.rectangle().mid_point()
        # 在推荐模块鼠标下拉,展示完整的为你推荐区域
        mouse.scroll(coords=(point.x, point.y), wheel_dist=-500)
        # 点击右滚动按钮
        scroll_left_ele = rec_ele["音乐补给右滚动"]
        one_one_ele = rec_ele["音乐补给第一排第一项文本"]
        two_one_ele = rec_ele["音乐补给第二排第一项文本"]

        one_one_text_before = QQMusic_app.win.child_window(auto_id=one_one_ele["auto_id"],
                                                           control_type=one_one_ele["control_type"],
                                                           found_index=0).window_text()
        two_one_text_before = QQMusic_app.win.child_window(auto_id=two_one_ele["auto_id"],
                                                           control_type=two_one_ele["control_type"],
                                                           found_index=0).window_text()

        scroll_right_btn = QQMusic_app.win.child_window(auto_id=scroll_left_ele["auto_id"],
                                                       control_type=scroll_left_ele["control_type"])
        scroll_right_btn.click_input()
        # 左滚动结果的校验--项目名称是否变化
        one_one_text_after = QQMusic_app.win.child_window(auto_id=one_one_ele["auto_id"],
                                                          control_type=one_one_ele["control_type"],
                                                          found_index=0).window_text()
        two_one_text_after = QQMusic_app.win.child_window(auto_id=two_one_ele["auto_id"],
                                                          control_type=two_one_ele["control_type"],
                                                          found_index=0).window_text()
        assert one_one_text_after != one_one_text_before
        assert two_one_text_after != two_one_text_before

歌词页面

歌词模块:测试歌词页面的标题、歌手名、歌曲名、测试歌词页面--测试歌词

测试歌词页面的标题、歌手名、歌曲名


'''
测试歌词页面的标题
“歌手名、歌曲名”
'''
    def test_titie_text(self,QQMusic_app):
        song_word_page_ele = read_yaml("歌词入口")
        song_word_btn = QQMusic_app.win.child_window(auto_id=song_word_page_ele["auto_id"],
                                     control_type=song_word_page_ele["control_type"])

        #点击页面的歌词入口,进入到歌词页面
        song_word_btn.click_input()
        #获取歌手名文本
        singer_text_ele = song_word_page_ele["歌手标题文本"]
        singer_text = QQMusic_app.win.child_window(auto_id=singer_text_ele["auto_id"],
                                     control_type=singer_text_ele["control_type"]).window_text()
        #校验歌手名文本
        assert singer_text == "刀郎"
        #获取歌曲名文本
        song_text_ele = song_word_page_ele["歌曲名标题文本"]
        song_text = QQMusic_app.win.child_window(auto_id=song_text_ele["auto_id"],
                                                   control_type=song_text_ele["control_type"]).window_text()
        #校验歌曲名文本
        assert song_text == "2002年的第一场雪"
   

测试歌词页面--测试歌词
从头播放歌曲并立即暂停————才能获取到歌词列表中的歌手名和歌曲名

'''
歌词页面——测试歌词
从头播放歌曲并立即暂停————才能获取到歌词列表中的歌手名和歌曲名
'''
    def test_songwords(self,QQMusic_app):
        likepage_ele = read_yaml("我喜欢")
        wordspage_ele = read_yaml("歌词入口")
        #收起歌词页面
        hide_word_page_ele = wordspage_ele["收起歌词"]
        hide_word_page_btn = QQMusic_app.win.child_window(auto_id=hide_word_page_ele["auto_id"],
                                     control_type=hide_word_page_ele["control_type"])
        hide_word_page_btn.click_input()

        # 为后面的测试用例做准备————点击播放歌曲并立即暂停
        playAll_ele = likepage_ele["播放全部"]
        playAll_btn = QQMusic_app.win.child_window(auto_id=playAll_ele["auto_id"],
                                                   control_type=playAll_ele["control_type"])
        playAll_btn.click_input()
        # 立即暂停播放
        play_ele = read_yaml("播放控制")["播放"]
        play_btn = QQMusic_app.win.child_window(auto_id=play_ele["auto_id"],
                                                control_type=play_ele["control_type"])
        play_btn.click_input()

        # 获取当前正在播放的歌手名和歌曲名
        play_control_ele = read_yaml("播放控制")
        singer_name_ele = play_control_ele["歌手名"]
        song_name_ele = play_control_ele["歌曲名"]
        singer_name = QQMusic_app.win.child_window(auto_id=singer_name_ele["auto_id"],
                                     control_type=singer_name_ele["control_type"]).window_text()
        song_name = QQMusic_app.win.child_window(auto_id=song_name_ele["auto_id"],
                                     control_type=song_name_ele["control_type"]).window_text()

        # songwordsText = f"{song_name} - {singer_name}"

        #进入歌词页面
        song_word_page_ele = read_yaml("歌词入口")
        song_word_btn = QQMusic_app.win.child_window(auto_id=song_word_page_ele["auto_id"],
                                                     control_type=song_word_page_ele["control_type"])

        # 点击页面的歌词入口,进入到歌词页面
        song_word_btn.click_input()
        #测试歌词
        words_list_ele = wordspage_ele["歌词列表"]
        words_list = QQMusic_app.win.child_window(auto_id=words_list_ele["auto_id"],
                                                     control_type=words_list_ele["control_type"])
        for i in words_list.children():
            if i.window_text() in song_name or i.window_text() in singer_name:
                return
            self.logger.info(f"获取到的歌词:{i.window_text()}")
        #始终没有匹配上
        raise Exception(f"歌词匹配失败,song_name:{song_name},singer_name{singer_name}")

测试工具类:方便打印信息,和定位窗口

logUtils.py:日志打印

import logging
import time
import os.path

class InfoFilter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.INFO

class ErrFilter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.ERROR

class Logger:
    logger=None
    @classmethod
    def getlog(cls):
        # 创建日志对象
        if cls.logger is None:
            cls.logger=logging.getLogger(__name__)
            # 设置日志级别
            cls.logger.setLevel(logging.DEBUG)

            LOG_PATH="log/"
            if not os.path.exists(LOG_PATH):
                os.mkdir(LOG_PATH)

            # 2026-03-02.log
            now=time.strftime("%Y-%m-%d")

            logname=LOG_PATH+now+".log"
            info_logname=LOG_PATH+now+"_info.log"
            err_logname=LOG_PATH+now+"_err.log"

            # 创建总日志文件处理器
            handler=logging.FileHandler(logname,encoding="utf-8")

            # 创建info日志文件处理器
            info_handler=logging.FileHandler(info_logname,encoding="utf-8")
            # 添加文件过滤
            info_handler.addFilter(InfoFilter())

            # 创建err日志文件处理器
            err_handler=logging.FileHandler(err_logname,encoding="utf-8")
            # 添加文件过滤
            err_handler.addFilter(ErrFilter())

            # 设置日志格式
            formatter=logging.Formatter(
                "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d] - %(message)s"
            )

            handler.setFormatter(formatter)
            info_handler.setFormatter(formatter)
            err_handler.setFormatter(formatter)

            # 给logger对象添加handler
            cls.logger.addHandler(handler)
            cls.logger.addHandler(info_handler)
            cls.logger.addHandler(err_handler)
        return cls.logger

yamlUtils.py

import os
import yaml

def read_yaml(key):
    with open(os.getcwd()+"/data/elements.yml",mode="r",encoding="utf-8") as f:
        data=yaml.safe_load(f)
        return data[key]

仿QQ音乐启动与关闭

import pytest
from pywinauto import Application
from utils.logUtils import Logger


class QQmusicApp:
    def __init__(self):
        self.app_path = r"D:\qqmusic\qqmusic\QQMusic.exe"
        self.logger = Logger.getlog()
        self.app = None
        self.win = None

    #启动QQmusic程序
    def launch(self):
        try:
            # self.app = Application(backend="uia").start(self.app_path)
            #测试代码
            self.app = Application(backend="uia").connect(process=174720)
            #定位窗口
            self.win = self.app.window(title="QQMusic")
            self.win.wait("visible")
            self.logger.info("应用程序启动成功!")
            # self.win.print_control_identifiers()

        except Exception as e:
            self.logger.error(f"应用程序启动失败:{e}")

    #关闭QQmusic程序
    def close(self):
        if self.win:
            self.win.close()

@pytest.fixture(scope="session")
def QQMusic_app():
    QQmusic = QQmusicApp()
    QQmusic.launch()

    yield QQmusic

    QQmusic.close()

自动化测试全部通过图片实列

测试配置

六、测试报告

allure generate .\reports\source\ -o .\reports\html  生成测试报告

点击进入浏览器,生成测试报告

可以点击进去,查看相关测试用例

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐