公关网站建设,如何卸载win上的wordpress,淘宝店铺装修做代码的网站,什么网站做污水处理药剂的好序近期看到阿里云性能测试 PTS 接口测试开启免费公测#xff0c;本着以和大家交流如何实现高效的接口测试为出发点#xff0c;本文包含了我在接口测试领域的一些方法和心得#xff0c;希望大家一起讨论和分享#xff0c;内容包括但不仅限于#xff1a;服务端接口测试介绍接…序近期看到阿里云性能测试 PTS 接口测试开启免费公测本着以和大家交流如何实现高效的接口测试为出发点本文包含了我在接口测试领域的一些方法和心得希望大家一起讨论和分享内容包括但不仅限于服务端接口测试介绍接口测试自动化介绍接口测试自动化实践关于接口测试自动化的思考和总结服务端接口测试介绍什么是服务端一般所说的服务端是指为用户在 APP 或 PC 使用的互联网功能提供数据服务的背后的一切。以天猫精灵智能音箱系列的产品链路为例服务端便是网关包括网关在内之后的链路。什么是接口官方点说是计算机系统中两个独立的部件进行信息交换的共享边界。通俗点说就是服务端对外提供数据服务最常用的信息交换方式。提供数据服务的服务端是个可大可小的机构做的事大多不止一件它做了这么多事最终的目标是给 APP 或其它调用方使用于是服务端就派出了几个代表比如 API 1 负责提供用户信息API 2 负责提供设备信息API 3 负责提供播放的音频信息等等。同事服务端规定好跟 API 1 通讯的接头暗号是 param1param2…跟 API 2 通讯的接头暗号是 param3param4…而 params 就是接口参数就是用来告诉服务端你要什么服务具体的要求是什么。接口一般由三个部分组成协议、地址及参数。什么是接口测试一般讲的接口测试指的是对某个给定接口进行功能测试输入不同的参数时接口返回值是否正确。下图是经典的测试金字塔模型。在这个模型中越往下比例会占的越高也就是说在一个产品测试中单元测试比例是最高的依次是接口测试和UI自动化测试最顶端是人工测试部分。服务端接口测试在中部承上启下由此可见其重要性。为什么要做接口测试一般做接口测试有如下原因接口是服务端对外提供数据服务最常用的信息交换方式接口大部分内容都是数据通过数据对比我们可以推测到系统的逻辑测接口其实也就是测逻辑。接口测试相对容易实现自动化也容易实现持续集成且相对 UI 自动化也比较稳定可以减少人工回归测试人力成本与时间缩短测试周期支持后端快速发版需求。如何做接口测试前面提到接口是由这几个组成部分接口地址、请求协议、请求参数和预期结果。测试接口的步骤一般步骤是发送请求-解析结果-验证结果。简单来说接口测试就是参照接口文档调用接口看结果的返回是否跟文档说明一致另外再测试一下接口对异常逻辑的处理比如非法参数或边界值。深入来说接口测试的关注重点在于一、接口的数据逻辑是否正确。我们需要充分理解接口的功能内部是什么样的数据逻辑它与上下游交换了那些信息或资源不单纯地停留在参数调用和程序返回的表象数据。通俗地说就是要知道这个接口是干什么用的用到哪里每次调用会发生什么然后去检验改发生的有没有发生。二、接口对于异常参数的处理机制与上下游服务的容错。如下图所示被测接口 A 依赖上游服务 A那么服务 A 异常的时候被测接口是否很好的容错就很重要否则服务挂起或宕掉都是有可能的。另外作为服务提供方接口 B应当要充分兼容不同的使用场景、或不同版本的调用方的使用不能为了服务 E 做的需求除了 E 其它的服务使用者都用不了了。总的来说原则就是“上游不可靠下游要兼容”。接口测试自动化介绍什么是接口测试自动化接口测试自动化简单来讲就是功能测试用例脚本化然后执行脚本产生一份可视化测试报告。为什么要做接口测试自动化不管什么样的测试方式都是为了验证功能与发现 bug。那为什么要做接口测试自动化呢一句话概括就是是为了节省人力成本。具体来说包括以下几点减轻自己工作量把测试从枯燥的重复劳动的人工测试中解放出来协助手工测试完成很难模拟或无法模拟的的工作提高工作效率比如测试环境的自动化编译、打包、部署、持续集成甚至持续交付等。协助定位问题比如接口层发现问题了可以通过添加的 traceID 定位到日志错误或错误代码行尽早发现 Bug自动通知测试人员。一旦发现问题立即通知测试人员快速高效。接口测试自动化的规范这里结合我平常在做接口测试时的一些经验总结了一些接口测试自动化的规范抛砖引玉欢迎大家补充。文档准备磨刀不误砍柴工准备好分详细的接口相关文档能够帮助后续接口自动化测试工作的高效展开。相关文档包括但不限于一下内容1、《需求文档》明确定义了接口背后的业务场景即该接口是干什么用的用到哪里每次调用会发生什么等2、《接口文档》明确定义了接口名各个入参值各个返回值和其他相关信息3、《UI 交互图》明确定义了各单页面需展示的数据页面之间的交互等4、《数据表设计文档》明确定义了表字段规则、表 N 多 N 关系一对一、一对多、多对多等务必和相关需求方确认好文档中的信息是可靠且最新的只有依赖可靠的文档才能设计出正确详尽的接口用例才能得到最正确的结果。明确接口测试自动化需要的功能1、校验断言测试断言是自动化测试中的测试通过条件用于判断测试用例是否符合预期。所以支持对返回值校验是一个必须的功能。2、数据隔离数据隔离就是指具体的请求接口、参数、校验等数据做到与代码相隔离便于维护一旦需要调整接口用例、新增接口用例时可很快速的找到位置。隔离的另一个好处就是可复用框架可以推广给其他团队使用者可以使用相同的代码只需要根据要求填写各自用例即可测试起来。3、数据传递做到数据隔离可维护后数据传递是另外一个更重要的需求。接口测试时首先我们会实现单接口解耦后续按照业务场景组合多个接口。而数据传递是则是组合多个接口的必要条件它让接口用例之间可以做到向下传参。举个例子我们通过设备信息查询接口查询到当前天猫精灵音箱的设备信息该接口会返回一个 UUID接下来我们要通过用户信息查询接口去查询当前设备绑定的用户信息此时第二个接口的请求数据是需要从第一个接口用例中的返回中提取的。4、功能函数实际的业务场景测试会需要各种辅助功能的支持比如随机生成时间戳请求 ID随机的手机号码或位置信息等等此时我们就需要代码可以支持做到识别对应关键字时可以执行对应的功能函数进行填充。5、可配置目前测试环境包括但不限于日常、预发一、预发二、线上等等因此用例不单单只能在一个环境上执行需要同一份接口用例可以在日常、预发、线上等多个环境都可以执行。所以框架需要做到可配置便于切换调用不同的配置文件可以在不同的环境执行。6、日志日志包含执行的具体执行接口、请求方式、请求参数、返回值、校验接口、请求时间、耗时等关键信息日志的好处一来是可以便于在新增用例有问题时快速定位出哪里填写有问题二来是发现 bug 时方便向开发反馈提供数据开发可以从触发时间以及参数等信息快速定位到问题所在。7、可视化报告用例执行后就是到了向团队展示结果的时候了一个可视化的报告可以便于团队成员了解到每次自动化接口用例执行的成功数、失败数等数据。8、可持续集成对于已经有测试用例并测试完成的接口我们希望能够形成回归用例在下一个版本迭代或上线之前通过已有用例进行一个回归测试确保新上线的功能不影响已有功能。因此这就需要接口自动化测试是可持续集成的而不是一次性的。接口测试自动化框架选型结合我们对接口测试自动化框架的需求及目前市场上的很多测试工具的特点总结成下表这里简单列举一下1、fiddlerfiddler 是一个 HTTP 协议调试代理工具Web 和手机测试都会用到同时也支持接口测试。它能够记录并检查所有你的电脑和互联网之间的 http 通讯设置断点查看所有的“进出”Fiddler 的数据指 cookie,html,js,css 等文件。2、postman它是 Google 开发的一个插件安装在 Chrome 浏览器上能支持不同接口测试请求可以管理测试套件和自动化运行。弱点是自动化断言功能不强大不能和 Jenkins、代码管理库进行持续集成测试。3、wireshak这是一款抓包工具支持 TCP、UDP、HTTP 等协议。如果做底层网络数据测试一般都需要用到它但是用作接口测试它就有点不友好。因为刷新数据太快不好定位每个操作对应的接口。4、soupUIsoapUI 是一个开源测试工具通过 soap/http 来检查、调用、实现 Web Service 的功能/负载/符合性测试。该工具既可作为一个单独的测试软件使用也可利用插件集成到 Eclipsemaven2.XNetbeans 和 intellij 中使用。把一个或多个测试套件TestSuite组织成项目每个测试套件包含一个或多个测试用例TestCase每个测试用例包含一个或多个测试步骤包括发送请求、接受响应、分析结果、改变测试执行流程等。该工具能够支持接口自动化测试和接口性能测试也支持和 Jenkins 做持续集成测试。5、Java 代码做接口测试为什么要用代码做接口自动化测试呢一些工具功能是有限制很多公司需要一些特定的功能工具不支持只好用代码进行开发。一般用 Java 做自动化测试主要利用 httpclient.jar 包然后利用 JUnit 或者 TestNG 这样的单元测试工具进行测试用例的开发接着在 Jenkins 或我们的 aone 上创建一个 job进行持续集成测试。6、Python 代码做接口测试和 Java 一样用 Python 做接口测试可以利用一个功能强大的第三方库 Requests它能方便地创建接口自动化用例。Python 下的单元测试框架一般采用 unittest。生成测试报告一般选择 HTMLTestRunner.py。同样可以结合 Jenkins 做持续集成测试。接口测试自动化实践TestNG 与 Junit 对比综合性对比我在日常测试工作中使用的比较多的自动化测试工具是 Java 代码做接口测试这里先介绍下我对单元测试工具 TestNG 和 Junit 的对比。先用一张表格总结一下他们的特点对比。TestNG 与 JUnit 的相同点如下1、都有注解即都使用 annotation且大部分 annotation 相同2、都可以进行单元测试Unit test3、都是针对 Java 测试的工具TestNG 与 JUnit 的不同点如下1、TestNG 支持的注解更丰富如ExpectedExceptions、DataProvider 等2、JUnit 4 中要求BeforeClass、AfterClass 方法声明为 static这就限制了该方法中使用的变量必须是 static。而 TestNG 中BeforeClass 修饰的方法可以跟普通函数完全一样3、JUnit 只能使用 IDE 运行TestNG 的运行方式有命令行、ant 和 IDE4、JUnit 4 依赖性非常强测试用例间有严格的先后顺序。前一个测试不成功后续所有的依赖测试都会失败。TestNG 利用Test 的 dependsOnMethods 属性来应对测试依赖性问题。某方法依赖的方法失败它将被跳过而不是标记为失败。5、对于 n 个不同参数组合的测试JUnit 4 要写 n 个测试用例。每个测试用例完成的任务基本是相同的只是方法的参数有所改变。TestNG 的参数化测试只需要一个测试用例然后把所需要的参数加到 TestNG 的 xml 配置文件中或使用DataProvider 方式注入不同的参数。这样的好处是参数与测试代码分离非程序员也可以修改参数同时修改无需重新编译测试代码。6、JUnit 4 的测试结果通过 Green/Red bar 体现TestNG 的结果除了 Green/Red bar还有 Console 窗口和 test-output 文件夹对测试结果的描述更加详细方便定位错误。详细特性对比下面详细介绍一下 TestNG 与 Junit 特性对比1、框架整合SpringTestNGMaven 整合pom.xml 中增加 testng 依赖dependency groupIdorg.testng/groupId artifactIdtestng/artifactId version6.8.8/version scopetest/scope/dependency测试类增加 1 条注解ContextConfiguration(locations classpath:applicationContext.xml)并继承 AbstractTestNGSpringContextTests范例如下ContextConfiguration(locations classpath:applicationContext.xml) public class BaseTest extends AbstractTestNGSpringContextTests{ Test public void testMethods() { ...... } }SpringJunitMaven 整合pom.xml 中增加 junit 依赖!--Junit版本--dependency groupIdjunit/groupId artifactIdjunit/artifactId version4.4/version scopetest/scope/dependency测试类增加 2 条注解RunWith(SpringJUnit4ClassRunner.class)ContextConfiguration(locations classpath:applicationContext.xml),如下RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations classpath:applicationContext.xml) public class BaseTest{ Test public void testMethods() { ...... } }2、注解支持主要区别以下两点1、在 JUnit 4 中我们必须声明“BeforeClass”和“AfterClass”方法作为静态方法。TestNG 在方法声明中更灵活它没有这个约束。2、在 JUnit 4 中注释命名约定有点混乱例如“Before”“After”和“Expected”我们并不真正了解“Before”和“After”之前的内容以及要测试中的“预期” 方法。TestiNG 更容易理解它使用类似“BeforeMethod”“AfterMethod”和“ExpectedException”就很明了。3、异常测试“异常测试”是指从单元测试中抛出的异常此功能在 JUnit 4 和 TestNG 中都可实现。JUnit 4Test(expected ArithmeticException.class) public void divisionWithException() { int i 1/0; }TestNGTest(expectedExceptions ArithmeticException.class) public void divisionWithException() { int i 1/0; }4、忽略测试忽略测试意思是在单元测试哪些是可以被忽略的这个特性在两个框架都已经实现。JUnit 4Ignore(Not Ready to Run) Test public void divisionWithException() { System.out.println(Method is not ready yet); }TestNGTest(enabledfalse) public void divisionWithException() { System.out.println(Method is not ready yet); }5、超时测试时间测试意思是如果一个单元测试运行的时间超过了一个指定的毫秒数那么测试将终止并且标记为失败的测试这个特性在两个框架都已经实现。JUnit 4Test(timeout 1000) public void infinity() { while(true); }TestNGTest(timeOut 1000) public voi6、套件测试“套件测试”是指捆绑几个单元测试并一起运行。此功能在 JUnit 4 和 TestNG 中都可实现。然而两者都使用非常不同的方法来实现它。JUnit 4“RunWith”和“Suite”用于运行套件测试。下面的类代码表示在 JunitTest3 执行之后单元测试“JunitTest1”和“JunitTest2”一起运行。所有的声明都是在类内定义的。RunWith(Suite.class) Suite.SuiteClasses({ JunitTest1.class, JunitTest2.class }) public class JunitTest3 { }TestNGXML 文件用于运行套件测试。以下 XML 文件表示单元测试“TestNGTest1”和“TestNGTest2”将一起运行。suite nameMy test suite test nametesting classes class namecom.fsecure.demo.testng.TestNGTest1 / class namecom.fsecure.demo.testng.TestNGTest2 / /classes /test/suiteTestNG 可以做捆绑类测试也可以捆绑方法测试。凭借 TestNG 独特的“分组”概念每种方法都可以与一个组合相结合可以根据功能对测试进行分类(分组)。例如下面是一个有四个方法的类三个组(method1method2 和 method3)Test(groupsmethod1) public void testingMethod1() { System.out.println(Method - testingMethod1()); } Test(groupsmethod2) public void testingMethod2() { System.out.println(Method - testingMethod2()); } Test(groupsmethod1) public void testingMethod1_1() { System.out.println(Method - testingMethod1_1()); } Test(groupsmethod4) public void testingMethod4() { System.out.println(Method - testingMethod4()); }使用以下 XML 文件可以仅使用组“method1”执行单元测试。suite nameMy test suite test nametesting groups run include namemethod1/ /run /groups classes class namecom.fsecure.demo.testng.TestNGTest //classes /test /suite7、参数化测试“参数化测试”是指单位测试参数值的变化。此功能在 JUnit 4 和 TestNG 中都实现。然而两者都使用非常不同的方法来实现它。Junit4 参数化测试步骤如下1.通过Parameters 标识静态参数构造方法2.通过测试类构造方法引入参数3.测试方法使用参数RunWith(value Parameterized.class) public class JunitTest { private int number; public JunitTest6(int number) { this.number number; } Parameters public static CollectionObject[] data() { Object[][] data new Object[][] { { 1 }, { 2 }, { 3 }, { 4 } }; return Arrays.asList(data); } Test public void pushTest() { System.out.println(Parameterized Number is : number); } }缺点一个测试类只能有一个静态的参数构造方法测试类需要使用RunWith(Parameterized.class)无法兼容 spring-test 的 runnerRunWith(SpringJUnit4ClassRunner.class)会导致无法通过注解注入待测服务需要在测试类中添加一个构造方法一种冗余设计TestNG 参数化测试步骤如下1.通过dataProvider 注解标识参数构造方法2.测试方法在注解Test 中通过 dataProvider 属性指定参数构造方法便可在测试方法中使用参数Test(dataProvider Data-Provider-Function) public void parameterIntTest(Class clzz, String[] number) { System.out.println(Parameterized Number is : number[0]); System.out.println(Parameterized Number is : number[1]); }除此之外TestNG 还支持通过 testng.xml 构造参数public class TestNGTest { Test Parameters(valuenumber) public void parameterIntTest(int number) { System.out.println(Parameterized Number is : number); } }XML 文件的内容如下suite nameMy test suite test nametesting parameter namenumber value2/ classes class namecom.fsecure.demo.testng.TestNGTest / /classes /test /suite8、依赖测试“参数化测试”表示方法是依赖性测试它将在所需方法之前执行。如果依赖方法失败则所有后续测试将会被跳过不会被标记为失败。JUnit 4JUnit 框架着重于测试隔离; 目前它不支持此功能。TestNG它使用“dependOnMethods”来实现依赖测试如下Test public void method1() { System.out.println(This is method 1); }Test(dependsOnMethods{method1}) public void method2() { System.out.println(This is method 2); }TestNG 接口自动化实践参数化测试示例以 DeviceStatusHSFService 为例测试类如下public class DeviceStatusHSFServiceTest { private DeviceStatusHSFService deviceStatusHSFService; BeforeTest(alwaysRun true) public void beforeTest() { String envName System.getProperty(maven.env); //运行环境可配置 SwitchENV switchEnv new SwitchENV(envName); //运行环境可配置 deviceStatusHSFService HsfRepository.getConsumer(DeviceStatusHSFService.class, switchEnv.getEnv(), HSF, switchEnv.getHsfVersion(), aicloud-device-center, switchEnv.getTargetIp()).getTarget(); } Test(dataProvider updateDeviceStatus, dataProviderClass DeviceStatusHSFServiceTestDataProvider.class) public void updateDeviceStatusTest(Long userId, String uuid, DeviceStatus deviceStatus){ ResultBoolean result deviceStatusHSFService.updateDeviceStatus(userId, uuid, deviceStatus); System.out.println(traceId:EagleEye.getTraceId()result.toString()); Boolean res result.getResult(); assertTrue(res); }}其中通过 SwitchENV 类实现运行环境可配置/** * 自定义环境配置 */public class SwitchENV { /** * 运行环境 */ private Env env; /** * hsf环境 */ private String hsfVersion; /** * 目标机器 */ private String targetIp; /** * 环境名称 */ private String envName; public SwitchENV(String envName) { Properties prop new Properties(); // TODO: 本地自动化测试切换环境专用 if (envName null) { envName pre1; } switch (envName) { case online: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-online.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.ONLINE; break; } case pre1: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre1.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } case pre2: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre2.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } case pre3: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre3.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } default: try { throw new Exception(环境变量输入错误); } catch (Exception e) { e.printStackTrace(); } break; } hsfVersion prop.getProperty(hsfVersion).trim(); targetIp prop.getProperty(targetIp).trim(); this.envName envName; } public Env getEnv() { return env; } public String getHsfVersion() { return hsfVersion; } public String getTargetIp() { return targetIp; } public String getEnvName() { return envName; }}测试参数全部放在 DeviceStatusHSFServiceTestDataProvider 类中实现具体的请求接口、参数、校验等数据做到与代码相隔离。/** * 自定义环境配置 */public class SwitchENV { /** * 运行环境 */ private Env env; /** * hsf环境 */ private String hsfVersion; /** * 目标机器 */ private String targetIp; /** * 环境名称 */ private String envName; public SwitchENV(String envName) { Properties prop new Properties(); // TODO: 本地自动化测试切换环境专用 if (envName null) { envName pre1; } switch (envName) { case online: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-online.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.ONLINE; break; } case pre1: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre1.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } case pre2: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre2.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } case pre3: { InputStream in SwitchENV.class.getClassLoader().getResourceAsStream( config/application-pre3.properties); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } env Env.PREPARE; break; } default: try { throw new Exception(环境变量输入错误); } catch (Exception e) { e.printStackTrace(); } break; } hsfVersion prop.getProperty(hsfVersion).trim(); targetIp prop.getProperty(targetIp).trim(); this.envName envName; } public Env getEnv() { return env; } public String getHsfVersion() { return hsfVersion; } public String getTargetIp() { return targetIp; } public String getEnvName() { return envName; }}思考与总结对于接口自动化测试从用例设计到测试脚本实现总结起来需要我们具备如下思想模块化思想数据驱动思想关键字驱动思想模块化思想对于我们的接口自动化测试工程而言需要能够创建小而独立的可以描述的模块、片断以及待测应用程序的脚本。这些树状结构的小脚本组合起来就能组成能用于特定的测试用例的脚本。数据驱动思想简而言之就是测试脚本与测试数据分离。让测试数据独立于测试脚本单独存在解除脚本与数据之间的强耦合。测试脚本不再负责管理测试数据而测试数据在数据驱动测试中会以文件或者数据库的形式存在。脚本每次执行会机械的从数据文件或者数据库中读入测试数据根据测试数据的不同走进不同的测试路径。在整个测试中测试脚本是一成不变的它一直机械的执行它本身的代码而活着的是我们的测试数据集我们通过不同的数据控制测试脚本中代码的走向。这个思想能够避免测试数据杂糅在测试脚本中方便测试数据的扩展。再者在自动化测试中为了维持回归测试的稳定一致测试脚本应当尽量避免更改。在非数据驱动的情况下恰恰违背了这一原则。自动化测试中随着项目的深入测试脚本将会持续增多测试数据和脚本揉在一起维护起来将会是一件恐怖的事情出错在所难免所以这时不要这样做让数据和脚本分离坚持死的代码活的数据维护的大部分工作将只面向数据。关键字驱动思想这是一种更为高级的数据驱动测试核心思想是将测试用例的每个步骤单独封装成一个函数以这个函数名作为关键字将函数名及传参写入文件中每个步骤映射一行文件。通过解析文件的每行内容将内容拼成一个函数调用调用封装好的步骤函数就可以一步步执行测试案例。在一个关键字驱动测试中待测应用程序的功能和每个测试的执行步骤将被一起写到一个表中。这一个思想通过很少的代码来产生大量的测试用例。同样的代码在用数据表来产生各个测试用例的同时被复用。当我们的测试思想越靠近上述三种类型的思想接口测试的实现将越自动化。随着人工智能的不断发展AI浪潮下也将诞生更多的自动化测试工具比如采用人工智能技术通过某种自适应的算法来迭代我们的测试用例生成测试脚本。这意味着未来测试人员的努力方向将在设计出更加可靠、高效的自动化用例生成工具、脚本构建工具与测试执行工具而原先那些重复劳动的人工测试工作就让聪明的机器帮我们做吧。实战案例光学理论是没用的要学会跟着一起敲要动手实操才能将自己的所学运用到实际当中去这时候可以搞点实战案例来学习。电商项目实战web测试项目webApph5小程序 测试项目接口自动化测试实战项目Linux实战项目面试资料我们进阶学习自动化测试必然是为了找到高薪的工作下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料并且有字节大佬给出了权威的解答刷完这一套面试资料相信大家都能找到满意的工作。以上资料对于想要测试进阶的朋友们来说应该会很有帮助需要的小伙伴可以后台私信找我免费领取。总结我见过很多leader在面试的时候遇到处于迷茫期的大龄程序员比面试官年龄都大。这些人有一些共同特征可能工作了好几年更夸张的是7、8年工作内容的重复性比较高没有什么技术含量的工作。凡事要趁早特别是技术行业一定要提升技术功底丰富自动化项目实战经验这对于你未来几年职业规划以及测试技术掌握的深度非常有帮助。如果对你有帮助的话点个赞收个藏给作者一个鼓励。也方便你下次能够快速查找。如有不懂还要咨询下方小卡片博主也希望和志同道合的测试人员一起学习进步在适当的年龄选择适当的岗位尽量去发挥好自己的优势。我的自动化测试开发之路一路走来都离不每个阶段的计划因为自己喜欢规划和总结测试开发视频教程、学习笔记领取传送门