UiAutomator的详细介绍

UIAutomator作为一种高效的测试框架,通过自动化手段显著提升了用户界面(UI)测试的效率与准确性。它不仅支持自动生成功能测试用例,还允许开发者在不同设备上执行这些测试,确保了应用程序的一致性和稳定性。

以下是对 Android 自动化测试中的 UiAutomator 的详细介绍:

目录

一、UiAutomator

概述

核心组件

UiDevice

UiSelector

UiObject

UiCollection

UiScrollable

简单测试用例示例

优点

局限性

适用场景

在自动化测试中的应用

在用户界面测试中的应用

进行复杂测试

二、UiAutomator和Appium哪个更适合Android自动化测试?

技术特点层面

测试场景层面

团队能力和资源层面


一、UiAutomator

UIAutomator是一种专为Android平台设计的自动化测试框架,它使开发者能够轻松创建针对用户界面(UI)的测试脚本。不同于传统的手动测试方法,UIAutomator允许测试人员通过编程方式模拟用户行为,如点击、滑动等操作,从而验证应用程序在各种情况下的表现。这种技术不仅极大地提高了测试效率,还减少了人为错误的可能性。通过UIAutomator,开发者可以专注于更复杂的功能验证,而无需担心基础交互的正确性。它就像是一个虚拟的手指,在屏幕上执行命令,检查每个元素是否按预期工作。

概述

UiAutomator 是 Android 官方提供的一个强大的用户界面自动化测试框架,它允许开发者和测试人员编写自动化测试用例,对 Android 设备上的用户界面进行全面的测试,包括但不限于应用程序内和跨应用程序的交互操作,能模拟用户的各种操作行为,确保应用在不同设备和环境下的正常运行。

核心组件

UiDevice

设备对象,是 UiAutomator 的核心组件,作为与 Android 设备交互的主要入口,提供了一系列操作设备的方法。

通过UiDevice的getInstance(instrumentation)方法获取,可以通过UiDevice实例来检测设备的各种属性,比如获取屏幕的方向、尺寸等,还可以通过UiDevice实例来执行设备级别的操作,比如点击Home键、返回键等。

  • wakeUp():唤醒设备,将设备从睡眠状态唤醒。

  • sleep():使设备进入睡眠状态,模拟按下电源键让设备休眠。

  • pressHome()pressBack()pressMenu() 等:模拟用户按下设备的物理按键,像主页键、返回键、菜单键等。

  • findObject(UiSelector selector):使用 UiSelector 查找界面元素,UiSelector 可根据元素的不同属性(如文本、资源 ID、类名等)定位元素。

  • swipe(int startX, int startY, int endX, int endY, int steps):执行滑动操作,从 (startX, startY) 点滑动到 (endX, endY) 点,steps 决定滑动的步数。

  • drag(int startX, int startY, int endX, int endY, int steps):执行拖动操作,将元素从一个位置拖动到另一个位置。

UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
uiDevice.wakeUp();
uiDevice.swipe(500, 1000, 500, 500, 10);

UiSelector

用于获取某些符合条件的UI控件对象,用于定位 UI 元素的工具类,可根据多种条件定位元素。

常用的条件包括:

  • text(String text):根据元素的显示文本定位元素,例如 new UiSelector().text("OK") 可定位显示文本为 "OK" 的元素。

  • resourceId(String resourceId):根据元素的资源 ID 定位元素,例如 new UiSelector().resourceId("com.example.app:id/button") 可定位资源 ID 为 "com.example.app:id/button" 的元素。

  • className(String className):根据元素的类名定位元素,例如 new UiSelector().className("android.widget.Button") 可定位类名为 "android.widget.Button" 的元素。

// 通过资源id获取
new UiSelector().resourceId("com.yang.designsupportdemo:id/CollapsingToolbarLayout");
​
// 通过描述文件获取
new UiSelector().description("Navigate up")
​
// 通过className获取
new UiSelector().className("android.support.v7.widget.RecyclerView")

UiObject

代表一个UI控件/元素,提供对元素进行操作的方法。

通过uiDevice的findObject(UiSelector)方法获取,获取到UiObject实例后,就可以对UI控件进行相关的操作。如:

  • click():点击元素。

  • setText(String text):向文本框等输入元素输入文本。

  • getText():获取元素的显示文本。

  • isEnabled():判断元素是否可用。

UiObject textField = uiDevice.findObject(new UiSelector().resourceId("com.example.app:id/textField"));
textField.setText("Hello, UiAutomator");

UiCollection

代表UI控件集合,相当于ViewGroup,比如界面中有多个CheckBox时,可以通过类名获取到当前界面下的所有CheckBox,然后通过控件id获取指定的CheckBox对象:

// 获取指定的CheckBox对象
UiCollection uiCollection = new UiCollection(new UiSelector().className("类名"));
UiObject checkBox = uiCollection.getChild(new UiSelector().resourceId(""));

UiScrollable

代表可滚动的控件,比如打开设置的关于手机选项:

// 滑动列表到最后,点击About phone选项
UiScrollable settings = new UiScrollable(new UiSelector().className("android.support.v7.widget.RecyclerView"));
UiObject about = settings.getChildByText(new UiSelector().className("android.widget.LinearLayout"), "About phone");
about.click();

简单测试用例示例

测试用例通常继承自 InstrumentationTestCase,以下是一个简单的测试用例示例:

import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;

public class SimpleUiAutomatorTest extends InstrumentationTestCase {
    public void testUiAutomatorExample() throws UiObjectNotFoundException {
        UiDevice uiDevice = UiDevice.getInstance(getInstrumentation());
        uiDevice.wakeUp();

        // 查找并点击一个应用图标,假设其文本为 "MyApp"
        UiObject appIcon = uiDevice.findObject(new UiSelector().text("MyApp"));
        appIcon.click();

        // 查找并操作应用内的元素
        UiObject button = uiDevice.findObject(new UiSelector().resourceId("com.myapp:id/actionButton"));
        button.click();

        UiObject resultText = uiDevice.findObject(new UiSelector().resourceId("com.myapp:id/resultText"));
        String text = resultText.getText();
        assertEquals("Expected Result", text);
    }
}

优点

UIAutomator拥有诸多优势,使其成为Android开发者的首选工具之一。

系统级操作:可以跨越应用程序边界,实现不同应用之间的操作,如从主屏幕启动一个应用,再进入另一个应用进行操作,对于测试涉及多应用交互的场景非常方便。

深度交互能力:能深入 Android 系统底层的 UI 框架,处理各种复杂的 UI 操作,适合测试 Android 系统原生的 UI 元素和系统级功能,如通知栏操作、系统设置操作等。

元素查找多样性:提供多种元素查找方式,能满足不同元素查找需求,通过 UiSelector 可以灵活定位各种元素。

局限性

测试语言限制:主要支持 Java 语言编写测试脚本,对于不熟悉 Java 的测试人员可能有一定的技术门槛。

学习曲线:由于涉及到 Android 系统底层的知识,对于初学者来说,可能需要花费一定时间来熟悉其使用方法和 API,理解如何正确操作和查找元素。

适用场景

  • 功能测试:验证应用程序的各种功能是否正常,包括按钮点击、输入验证、页面跳转等。
  • 兼容性测试:在不同的 Android 设备和不同版本的 Android 系统上运行测试用例,确保应用程序在不同设备和系统上的兼容性。
  • 回归测试:当应用程序进行更新或修改时,使用 UiAutomator 可以快速对已有的功能进行重新测试,确保新的改动没有破坏原有功能。

在自动化测试中的应用

UIAutomator作为一款专门为Android平台打造的自动化测试工具,其强大之处在于它能够无缝地集成到现有的开发流程中,为开发者提供了一种高效且灵活的方式来验证应用程序的用户界面。通过简单的Java代码,即可实现对应用界面元素的操作与验证,比如模拟用户点击按钮、输入文本等常见交互行为。

不仅如此,UIAutomator还支持复杂的条件判断和循环结构,使得即使是面对高度动态变化的应用界面,也能编写出稳定可靠的测试脚本。

更重要的是,由于UIAutomator可以直接运行在Android设备或模拟器上,因此它能够真实地反映应用在实际运行环境中的表现,这对于发现潜在问题、优化用户体验具有不可替代的作用。例如,在一个典型的电商应用中,开发者可以利用UIAutomator来模拟用户浏览商品、添加购物车、结算支付等一系列操作流程,从而全面检查整个购物流程的顺畅度及功能性。

在用户界面测试中的应用

当谈到如何有效地运用UIAutomator进行用户界面测试时,我们不得不提到它那令人印象深刻的灵活性与实用性。

想象一下,当你面对着一个全新的应用项目,每一个像素都充满了未知与挑战,这时UIAutomator就像是一位忠实的朋友,引领你穿越复杂的界面迷宫。通过编写简洁明了的Java代码,开发者可以轻松地模拟出几乎所有的用户交互行为——从简单的点击到复杂的多点触控手势,甚至是键盘输入和菜单选择。

更重要的是,UIAutomator的强大之处不仅仅体现在它能够执行这些基本操作上,更在于它能够帮助开发者构建起一套完整的测试体系。例如,在一个典型的社交应用中,你可以编写一系列测试用例来验证登录流程、发布状态更新、查看好友列表等功能是否按预期工作。每一项测试都可以被细致地分解成多个步骤,通过UIAutomator提供的API逐一实现。而这一切的背后,是无数个精心编写的代码片段,它们如同乐高积木般组合在一起,共同构成了一个稳固且高效的测试框架。

为了更好地理解这一点,让我们来看一个具体的例子。假设我们需要测试一个电商应用中的购物车功能,确保用户能够顺利地将商品添加到购物车,并且能够正确显示商品数量。

这里,我们可以使用UiDevice类来获取当前设备实例,并通过click()方法模拟点击“添加到购物车”按钮的动作。接着,利用UiObject类及其子类UiSelector来查找购物车图标,并再次调用click()方法打开购物车页面。最后,通过检查页面上显示的商品数量是否与预期相符来验证功能的正确性。这样的测试不仅能够覆盖常见的使用场景,还能帮助发现潜在的设计缺陷或逻辑错误,从而确保最终产品的质量。

进行复杂测试

在面对复杂的应用逻辑和多变的用户行为模式时,如何确保每一个功能点都能得到充分测试是一个巨大的挑战。

幸运的是,UIAutomator为此提供了强有力的解决方案。通过组合使用多种选择器和条件判断语句,开发者可以构建出高度定制化的测试脚本,以适应几乎任何类型的测试需求。

例如,在一个在线教育平台上,开发者可能需要验证学生能否顺利地观看课程视频、提交作业以及参与实时讨论。此时,可以利用UIAutomator来模拟用户从登录账号、进入课程页面直到完成一系列互动操作的全过程。据统计,某在线教育平台通过采用UIAutomator进行自动化测试后,其用户反馈中的技术问题减少了约35%,这直接反映了自动化测试对于提升用户体验的重要性。

不仅如此,UIAutomator还支持异步操作的测试,这对于那些涉及后台数据加载或网络请求的功能尤为关键。通过合理设置等待时间和超时机制,测试脚本能确保在适当的时候检查应用的状态,从而避免了因网络延迟等原因导致的误判。总之,UIAutomator以其强大的功能和灵活性,成为了应对复杂测试挑战的理想选择,帮助开发者们在激烈的市场竞争中脱颖而出。


总之,UiAutomator 是 Android 自动化测试领域的一个重要工具,它为开发人员和测试人员提供了丰富的功能,能够帮助确保 Android 应用程序的质量和用户体验,尤其在处理系统级操作和 Android 原生 UI 测试方面表现出色。

二、UiAutomator和Appium哪个更适合Android自动化测试?

UiAutomator 和 Appium 在 Android 自动化测试方面各有优劣,哪一个更适合取决于具体的测试需求和场景,以下从不同角度来对比分析它们各自的适用性:

技术特点层面

(1)UiAutomator

优势:

  • 对 Android 系统原生支持强:作为 Android 官方推出的框架,它与 Android 系统底层的 UI 框架深度结合,可以直接访问和操作系统原生的各种 UI 元素,对于像系统设置、通知栏等系统级的功能测试以及一些 Android 原生应用中复杂且深度的 UI 交互测试,能更精准、高效地进行操作。例如,测试修改系统的显示设置、从通知栏中清除通知等操作,UiAutomator 可以很方便地实现。

  • 执行效率相对较高:由于是专门针对 Android 定制开发,不存在跨平台兼容等额外的抽象层开销,在 Android 设备上运行测试脚本时,执行速度通常较快,尤其是针对纯 Android 原生应用且涉及大量系统级操作的测试场景,能更快速地完成测试任务。

劣势:

  • 语言限制明显:主要依赖 Java 语言来编写测试脚本,这对于那些不熟悉 Java 或者团队中使用多种编程语言的情况来说,不太友好,限制了更多技术人员参与到测试脚本编写工作中,也可能增加学习成本和协作难度。

  • 跨平台能力缺失:只能应用于 Android 设备,无法用于 iOS 或其他操作系统平台的测试,如果开发的应用需要在多平台上进行测试,单独使用 UiAutomator 就无法满足需求。

(2)Appium

优势:

  • 跨平台特性显著:支持包括 Android、iOS 等多种主流移动操作系统的自动化测试,使用同一套测试脚本,只需做少量调整(甚至无需调整,取决于应用的设计和测试场景)就能在不同平台的设备上运行,非常适合需要同时兼顾多平台应用开发和测试的团队,比如一个移动端应用要同时发布在安卓和苹果手机上,Appium 可以极大地提高测试效率,降低测试成本。

  • 多语言支持方便协作:支持诸如 Java、Python、JavaScript、Ruby 等多种编程语言,不同技术背景的测试人员可以根据自己熟悉的语言来编写测试脚本,便于团队成员之间的协作,也更容易在项目中集成自动化测试环节,降低了对特定语言的依赖门槛。

劣势:

  • 执行效率略逊一筹:因为要兼容多个不同的移动操作系统平台,在底层进行了较多的抽象和适配工作,这使得其在执行测试脚本时,相比专注于 Android 的 UiAutomator,速度上可能会稍慢一些,不过在很多实际应用场景中,这种效率差异往往不会成为决定性因素。

  • 对系统原生功能深度测试有限:虽然可以通过调用各平台的原生框架(如在 Android 上借助 UiAutomator 等)来进行操作,但相对来说,在对 Android 系统的一些深层次、系统原生特有的功能测试方面,不如 UiAutomator 直接和灵活,毕竟其设计重点是跨平台的通用性操作。

测试场景层面

(1)功能测试场景

UiAutomator如果是对 Android 应用中那些依赖于系统原生特性实现的功能,或者需要深度访问 Android 系统底层 UI 的功能进行测试,例如测试 Android 应用中与系统服务有紧密交互的功能,像调用摄像头、麦克风权限相关的功能模块,UiAutomator 会是更好的选择,它能更精准地模拟相关操作并验证功能是否正常。

Appium对于一些常见的、通用的用户操作功能测试,比如登录、注册、表单提交、页面跳转等基本的应用交互功能,无论在 Android 还是其他支持的平台上,Appium 都能很好地完成测试任务,并且方便在多平台间进行对比测试,确保功能的一致性。

(2)兼容性测试场景

UiAutomator单独使用时只能针对 Android 设备的不同机型、不同 Android 版本进行兼容性测试,不过在 Android 系统内,它可以很好地检查应用在各种系统环境下是否能正常运行,尤其是涉及系统级功能的兼容性情况。

Appium在需要同时验证应用在 Android 和 iOS 等多个不同平台上的兼容性时,具有绝对优势,能够快速在不同操作系统的设备上运行相同的测试用例,查看应用是否在不同平台的界面显示、功能交互等方面都能符合预期,帮助开发团队及时发现并解决因平台差异导致的兼容性问题。

(3)回归测试场景

UiAutomator适合对 Android 应用中已有的、与系统原生特性关联紧密的功能进行回归测试,当应用更新后,快速验证那些涉及系统底层 UI 交互的功能是否依然稳定,例如应用中某些与系统通知相关的功能模块,在更新后是否正常工作。

Appium更侧重于对整个应用在多平台下的整体功能进行回归测试,确保之前测试通过的功能在不同平台上没有因为代码修改或更新而出现问题,方便开发团队从多平台角度把控应用的质量稳定性。

团队能力和资源层面

(1)团队成员语言技能分布

如果团队成员大多熟悉 Java 语言,且测试工作主要聚焦在 Android 系统内,那么 UiAutomator 使用起来会比较顺手,能充分发挥团队成员的技术优势,高效地编写和执行测试脚本。

要是团队成员技术背景多样,涵盖了不同编程语言的使用者,并且有跨平台测试的需求,那么 Appium 的多语言支持特性就会更契合团队情况,便于各个成员参与到自动化测试工作中。

(2)社区资源与技术支持

UiAutomator 主要依托 Android 官方的支持以及部分 Android 开发者社区的资源分享,相对来说资源集中在 Android 相关的测试应用场景上,遇到问题时可参考的官方文档和相关案例有一定的局限性。

Appium 拥有庞大的全球社区,涵盖了多平台的使用案例、技术分享、问题解决方案等丰富资源,无论是新手入门学习还是在测试过程中遇到复杂问题,都更容易从社区中获取到有效的帮助,这对于长期的自动化测试工作开展和持续优化是一个很大的优势。


综上所述,不能简单地说 UiAutomator 和 Appium 哪个更适合 Android 自动化测试。如果测试工作侧重于 Android 系统原生功能、对执行效率要求较高且团队成员熟悉 Java 语言,那么 UiAutomator 更为合适;而若有跨平台测试需求、团队成员技术背景多样且希望借助丰富的社区资源来支持测试工作,Appium 则会是更好的选择。在实际应用中,甚至可以考虑将两者结合使用,发挥各自的长处,以达到最佳的 Android 自动化测试效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/960499.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot源码解析(八):Bean工厂接口体系

SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 SpringBoot源码解析(四):解析应用参数args Sp…

Agent群舞,在亚马逊云科技搭建数字营销多代理(Multi-Agent)(下篇)

在本系列的上篇中,小李哥为大家介绍了如何在亚马逊云科技上给社交数字营销场景创建AI代理的方案,用于社交动态的生成和对文章进行推广曝光。在本篇中小李哥将继续本系列的介绍,为大家介绍如何创建主代理,将多个子代理挂载到主代理…

美国本科申请文书PS写作中的注意事项

在完成了introduction之后,便可进入到main body的写作之中。美国本科申请文书PS的写作不同于学术论文写作,要求你提出论点进行论证之类。PS更多的注重对你自己的经历或者motivation的介绍和描述。而这一描述过程只能通过对你自己的过往的经历的展现才能体…

2024.1.22 安全周报

政策/标准/指南最新动态 01 工信部印发《关于加强互联网数据中心客户数据安全保护的通知》 原文: https://www.secrss.com/articles/74673 互联网数据中心作为新一代信息基础设施,承载着千行百业的海量客户数据,是关系国民经济命脉的重要战略资源。…

Brave132 编译指南 Windows 篇:安装 Visual Studio 2022(二)

1. 引言 在着手编译 Brave 浏览器的 132 版本之前,构建一个完备的开发环境至关重要。Visual Studio 2022 作为一款功能强大的集成开发环境(IDE),为 Brave 浏览器的编译提供了坚实的工具链和技术支持。它不仅提供了高效的代码编辑…

【go语言】并发编程

一、协程、线程、进程 在计算机编程中,进程、线程和协程都是用于并发执行任务的不同概念。他们的区别主要体现在创建、管理和调度的复杂度上,特别是在不同的编程语言中有不同的实现方式。下面是他们的详细区别和在 go 语言中的实现方式。 1.1 进程 定义…

day6手机摄影社区,可以去苹果摄影社区学习拍摄技巧

逛自己手机的社区:即(手机牌子)摄影社区 拍照时防止抖动可以控制自己的呼吸,不要大喘气 拍一张照片后,如何简单的用手机修图? HDR模式就是让高光部分和阴影部分更协调(拍风紧时可以打开&…

1905电影网中国地区电影数据分析(一) - 数据采集、清洗与存储

文章目录 前言一、数据采集步骤及python库使用版本1. python库使用版本2. 数据采集步骤 二、数据采集网页分析1. 分析采集的字段和URL1.1 分析要爬取的数据字段1.2 分析每部电影的URL1.2 分析每页的URL 2. 字段元素标签定位 三、数据采集代码实现1. 爬取1905电影网分类信息2. 爬…

Qpython+Flask监控添加发送语音中文信息功能

对QpythonFlask实现对小孩学习的监控-CSDN博客中html页面进行改造,利用Ajax,提交一段文字,发送到数据库,再在服务器,发送该段文件给手机端,然手机端TTS朗读出来,增加了父母监控小孩学习&#xf…

【note】MCTS

MCTS survey 参考 http://arxiv.org/abs/2103.04931 基本概念 MDP 可以表示为一个四元组 ( S , A S , P a , P w ) (S,A_S,P_a,P_w) (S,AS​,Pa​,Pw​): S S S:状态空间 A s A_s As​:状态 s s s 下的可行动作集合 P a ( s , s ′ ) P_…

Couchbase UI: Server

在 Couchbase UI 中的 Server(服务器)标签页主要用于管理和监控集群中的各个节点。以下是 Server 标签页的主要内容和功能介绍: 1. 节点列表 显示集群中所有节点的列表,每个节点的详细信息包括: 节点地址&#xff1…

顶刊JFR|ROLO-SLAM:首个针对不平坦路面的车载Lidar SLAM系统

摘要 基于激光雷达(LiDAR)的同步定位与地图构建(SLAM)被认为是在恶劣环境中提供定位指导的一种有效方法。然而,现成的基于激光雷达的SLAM方法在经过不平坦地形时,尤其是在垂直方向相关的部分,会…

枪支消音器的 CFD 模拟

探索应用于枪支消音器的计算流体动力学的迷人世界。 了解枪支消音器 枪支消音器,也称为抑制器,是安装在枪支枪管上的装置,用于降低子弹发射时产生的噪音。消音器的作用是减缓和冷却子弹离开枪管时迅速膨胀的热气体。这一过程有助于降低声音…

Object类(1)

大家好,今天我们来学习一个常用类-Object类,这个类可以说是所有类的父类,因此它的重要性不言而喻,那么话不多说,来看。 大家可能会有一个疑问,java中不是只能继承一个类吗,那么我们继承了Objec…

【数据资产】数据资产管理概述

导读:数据资产管理在企业的数字化转型和业务发展中扮演着至关重要的角色。它直接关系到企业的决策效率、运营优化、业务创新以及风险防控等多个方面。数据资产作为企业的重要战略资源,能够为企业带来经济利益,其价值可能来自于数据本身的稀缺…

Qt监控系统辅屏预览/可以同时打开4个屏幕预览/支持5x64通道预览/onvif和rtsp接入/性能好

一、前言说明 在监控系统中,一般主界面肯定带了多个通道比如16/64通道的画面预览,随着电脑性能的增强和多屏幕的发展,再加上现在监控摄像头数量的增加,越来越多的用户希望在不同的屏幕预览不同的实时画面,一个办法是打…

51单片机开发:独立键盘实验

实验目的:按下键盘1时,点亮LED灯1。 键盘原理图如下图所示,可见,由于接GND,当键盘按下时,P3相应的端口为低电平。 键盘按下时会出现抖动,时间通常为5-10ms,代码中通过延时函数delay…

【翻转硬币——莫比乌斯函数、分块、卷积、埃氏筛】

题目 暴力代码&#xff0c;官网过55% #include <bits/stdc.h> using namespace std; int main() {int n;cin >> n;vector<bool> a(n 1);a[1] 1;int res 1;for (int i 2; i < n; i){if (a[i] 0){for (int j i; j < n; j i)a[j] a[j] ^ 1;res;}…

Hive:内部表和外部表,内外转换

内部表和外部表 内部表示例 给表添加数据 外部表示例 给表添加数据 外部表示例 用location指定表目录位置,那么表的位置在实际指定的位置,但是可以被映射 外部表和内部表的区别 删除表后使用show tables in shao; 已经没有被删除的表,说明元数据已经被删除(mysql里面存放),但是…