diff --git a/_config.yml b/_config.yml index b672c3a..b9529c5 100644 --- a/_config.yml +++ b/_config.yml @@ -10,7 +10,7 @@ aux_links: mermaid: # Version of mermaid library # Pick an available version from https://cdn.jsdelivr.net/npm/mermaid/ - version: "10.5.1" + version: "10.8.1" # For copy button on code diff --git a/docs/Database/mysql.md b/docs/Database/mysql.md index 640a90b..8d44bd5 100644 --- a/docs/Database/mysql.md +++ b/docs/Database/mysql.md @@ -72,6 +72,7 @@ EXPLAIN SELECT * FROM users WHERE age > 25; * **select_type**: 查询的类型(例如 SIMPLE, SUBQUERY, DERIVED 等)。 * **table**: 输出的表名。 * **type**: 访问类型(例如 ALL, index, range, ref, eq_ref, const, system, NULL)。 + https://www.cnblogs.com/xxoome/p/14434061.html **务必浏览此文档** * **possible_keys**: 可能使用的索引。 * **key**: 实际使用的索引。 * **key_len**: 使用的索引的长度。 @@ -79,4 +80,22 @@ EXPLAIN SELECT * FROM users WHERE age > 25; * **rows**: 估计需要检查的行数。 * **Extra**: 额外的信息,如 "Using where", "Using index", "Using temporary", "Using filesort" 等。 -为了获得最佳的性能,你应该经常使用 `EXPLAIN` 来检查你的查询,并根据其建议进行优化。 \ No newline at end of file +为了获得最佳的性能,你应该经常使用 `EXPLAIN` 来检查你的查询,并根据其建议进行优化。 + + +# 4. InnoDB和MyISAM的区别 + +InnoDB和MyISAM是MySQL数据库管理系统中最常用的两种存储引擎,它们在处理数据库事务、锁定机制、存储方式等方面有一些显著的区别。 + +1. 事务处理:InnoDB支持事务处理,具有ACID特性,提供了更好的数据完整性和并发性能。 + 而MyISAM不支持事务处理,这意味着它无法提供数据的原子性、一致性、隔离性和持久性保证。 +2. 锁定机制:InnoDB支持行级锁定,这可以提高并发访问的性能,因为它允许多个事务同时访问不同的数据行。 + 而MyISAM只支持表级锁定,当对一个表进行操作时,会锁定整个表,这可能会降低并发性能。 +3. 存储方式:InnoDB将数据存储在磁盘上的InnoDB表空间数据文件中,表的大小只受限于操作系统文件的大小。 + 而MyISAM将数据存储在三个文件中,包括表定义文件(.frm)、数据文件(.MYD)和索引文件(.MYI)。 +4. 外键支持:InnoDB支持外键约束,这有助于维护数据的引用完整性。而MyISAM则不支持外键。 +5. 性能:在某些情况下,MyISAM的性能可能会比InnoDB更好,尤其是在执行大量的SELECT查询时。 + 这是因为MyISAM的表强调的是性能,其执行速度比InnoDB更快。然而,在需要执行大量的INSERT、UPDATE或DELETE操作时, + InnoDB通常表现更好,因为它支持事务处理和行级锁定。 + +综上所述,InnoDB和MyISAM各有其优点和适用场景。在选择存储引擎时,应根据具体的应用需求和性能要求来决定使用哪种引擎。 \ No newline at end of file diff --git "a/docs/spring/kafka\351\235\242\350\257\225.md" "b/docs/spring/kafka\351\235\242\350\257\225.md" new file mode 100644 index 0000000..ac1e523 --- /dev/null +++ "b/docs/spring/kafka\351\235\242\350\257\225.md" @@ -0,0 +1,29 @@ +--- +layout: default +title: kafka面试 +parent: Spring +--- + + + + +1. 请简述Kafka是什么,以及它的主要用途。 +2. Kafka的基本架构是怎样的?能否详细解释一下各个组件的作用? +3. 在Kafka中,生产者发送消息的过程是怎样的?有哪些关键的配置参数? +4. Kafka中的消费者是如何消费消息的?它支持哪些消费模式? +5. Kafka是如何保证消息的高可用性和持久性的?它的数据是如何存储和复制的? +6. 请描述一下Kafka的分区策略和分区数对性能和可用性的影响。 +7. Kafka支持哪些数据压缩算法?它们对性能和存储的影响是什么? +8. 在Kafka中,如何处理消息的延迟和堆积问题? +9. Kafka的容错机制是怎样的?当Broker宕机时,如何保证消息不丢失? +10. Kafka与传统的消息队列系统(如RabbitMQ、ActiveMQ)相比,有哪些优势和不足? +11. Kafka在哪些场景下适用?是否有一些使用Kafka的最佳实践? +12. 请描述一下Kafka的扩展性和伸缩性。如何根据业务需求调整Kafka集群的规模? +13. Kafka的监控和运维有哪些工具和方法?如何保证Kafka的稳定性和性能? +14. 在Kafka中,如何处理消息的幂等性和去重问题? +15. Kafka是否支持事务消息?如果支持,它是如何实现的? +16. 请简述Kafka的流处理功能。它与传统的消息队列系统有何不同? +17. Kafka与其他大数据处理组件(如Hadoop、Spark)是如何集成的? +18. Kafka的安全性如何保障?它支持哪些认证和授权机制? + + diff --git "a/docs/spring/rocketmq\351\235\242\350\257\225.md" "b/docs/spring/rocketmq\351\235\242\350\257\225.md" new file mode 100644 index 0000000..c3ebdfe --- /dev/null +++ "b/docs/spring/rocketmq\351\235\242\350\257\225.md" @@ -0,0 +1,27 @@ +--- +layout: default +title: rocketmq面试 +parent: Spring +--- + +1. 请简述RocketMQ的主要概念和特点。 +2. RocketMQ中的Broker和NameServer分别扮演什么角色? +3. 在RocketMQ中,生产者发送消息的负载均衡是如何实现的? +4. 请描述一下RocketMQ的消费者订阅消息的负载均衡策略。 +5. RocketMQ是如何保证消息的高可用性的? +6. 请描述一下RocketMQ的工作流程。 +7. RocketMQ的存储机制是怎样的?它的存储结构有何特点? +8. 为什么RocketMQ的性能比较高?有哪些因素影响了它的性能? +9. 在RocketMQ中,消息被消费后会被立即删除吗?消息会如何被清理? +10. 请描述一下RocketMQ的部署架构和部署类型,以及它们的特点。 +11. 你是否有过部署RocketMQ的经验?如果有,请描述一下你当时的部署过程。 +12. RocketMQ如何处理消息的持久化和可靠性? +13. 请简述RocketMQ中的Topic和JMS的Queue之间的区别。 +14. RocketMQ支持哪些消息模式?请详细描述一下。 +15. 在RocketMQ中,如何保证消息的顺序性? +16. RocketMQ的监控和运维有哪些工具和方法? +17. 请描述一下RocketMQ中的事务消息是如何实现的。 +18. RocketMQ如何处理消息的延迟和定时发送? +19. 请简述RocketMQ中的消息过滤机制。 +20. 在RocketMQ中,如何处理消息的重复消费问题? + diff --git a/docs/spring/zookeeper.md b/docs/spring/zookeeper.md index 15ec625..4c51891 100644 --- a/docs/spring/zookeeper.md +++ b/docs/spring/zookeeper.md @@ -8,11 +8,12 @@ parent: Spring ## 1.1. 特点 -- 分布性系统在空间维度,不是集中统一,是随意分布 -- 没有主次之分,没有方便管理和被管理的角色,各节点是对等的,但是有副本(对数据和服务冗余的一种方式) -- 并发性:分布式系统会并发的读写一些被共享的存储数据,需要准确高效地协调这些并发操作 -- 缺乏全局时钟:读写存在时序性,谁先谁后,需一个全局的时钟序列控制 -- 故障总会发生 +1. 分布性系统在空间维度,不是集中统一,是随意分布 +2. 没有主次之分,没有方便管理和被管理的角色,各节点是对等的,但 + 是有副本(对数据和服务冗余的一种方式) +3. 并发性:分布式系统会并发的读写一些被共享的存储数据,需要准确高效地协调这些并发操作 +4. 缺乏全局时钟:读写存在时序性,谁先谁后,需一个全局的时钟序列控制 +5. 故障总会发生 ## 1.2. 问题 diff --git "a/docs/spring/\344\272\213\345\212\241.md" "b/docs/spring/\344\272\213\345\212\241.md" index 9896cc4..823949d 100644 --- "a/docs/spring/\344\272\213\345\212\241.md" +++ "b/docs/spring/\344\272\213\345\212\241.md" @@ -6,26 +6,28 @@ parent: Spring # 1. 事务的特性 -- 原子性(Atomicity): 事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。 - -- 一致性(Consistency): 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。 - -- 隔离性(Isolation): 一个事务的执行不能被其他事务干扰。 - -- 持续性/永久性(Durability): 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。 +1. 原子性(Atomicity): 事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。 +2. 一致性(Consistency): 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。 + 一致性与原子性是密切相关的。 +3. 隔离性(Isolation): 一个事务的执行不能被其他事务干扰。 +4. 持续性/永久性(Durability): 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。 # 2. 脏读、不可重复读、幻读 -- 脏读:事务A读取事务B没有提交的数据,如余额B修改前是1000,修改后是2000,事务读取了2000,但B发生异常,回滚后,真实的金额是1000,所以A读取的脏数据 -- 不可重复读:事务A第一次读取了单据的状态是未提交,去请求一个较长的IO数据,事务B把这个单据状态给置为取消了,事务A的IO结束,再取一次单据的状态,和第一次不一样,就是不可重复读 -- 幻读:事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。 +1. 脏读:事务A读取事务B没有提交的数据,如余额B修改前是1000,修改后是2000,事务读取了2000, + 但B发生异常,回滚后,真实的金额是1000,所以A读取的脏数据 +2. 不可重复读:事务A第一次读取了单据的状态是未提交,去请求一个较长的IO数据,事务B把这个单据状态给置为取消了, + 事务A的IO结束,再取一次单据的状态,和第一次不一样,就是不可重复读 +3. 幻读:事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后, + 这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。 > 不可重复读和幻读的区别是,前者是update,后者是insert # 3. 事务的隔离级别 -mysql中,默认的事务隔离级别是可重复读(repeatable-read),为了解决不可重复读,innodb采用了MVCC(多版本并发控制)来解决这一问题。 -MVCC是利用在每条数据后面加了隐藏的两列(创建版本号和删除版本号),每个事务在开始的时候都会有一个递增的版本号,用来和查询到的每行记录的版本号进行比较。 +Mysql中,默认的事务隔离级别是**可重复读(repeatable-read)**,为了解决不可重复读,Innodb采用了MVCC(多版本并发控制)来解决这一问题。 +MVCC是利用在每条数据后面加了隐藏的两列(创建版本号和删除版本号),每个事务在开始的时候都会有一个递增的版本号, +用来和查询到的每行记录的版本号进行比较。 MYSQL MVCC | 事务级别 | 脏读 | 不可重复读 | 幻读 | @@ -41,13 +43,12 @@ MYSQL MVCC 在事务A中,存在事务B,就出现了事务的传播。Spring中事务的传播有以下几类: -Spring 中org.springframework.transaction.annotation.Propagation类的定义 - ```java +// Spring中org.springframework.transaction.annotation.Propagation类的定义 public enum Propagation { // 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务 - //当前方法存在事务时,子方法加入该事务。此时父子方法共用一个事务,无论父子方法哪个发生异常回滚,整个事务都回滚。即使父方法捕捉了异常,也是会回滚。而当前方法不存在事务时,子方法新建一个事务。 - + //当前方法存在事务时,子方法加入该事务。此时父子方法共用一个事务,无论父子方法哪个发生异常回滚, + // 整个事务都回滚。即使父方法捕捉了异常,也是会回滚。而当前方法不存在事务时,子方法新建一个事务。 REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), // 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 @@ -57,7 +58,8 @@ public enum Propagation { MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), // 创建一个新的事务,如果当前存在事务,则把当前事务挂起。 - // 无论当前方法是否存在事务,子方法都新建一个事务。此时父子方法的事务时独立的,它们都不会相互影响。但父方法需要注意子方法抛出的异常,避免因子方法抛出异常,而导致父方法回滚。 + // 无论当前方法是否存在事务,子方法都新建一个事务。此时父子方法的事务时独立的, + // 它们都不会相互影响。但父方法需要注意子方法抛出的异常,避免因子方法抛出异常,而导致父方法回滚。 REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), @@ -68,7 +70,8 @@ public enum Propagation { NEVER(TransactionDefinition.PROPAGATION_NEVER), // 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED - // 当前方法存在事务时,子方法加入在嵌套事务执行。当父方法事务回滚时,子方法事务也跟着回滚。当子方法事务发送回滚时,父事务是否回滚取决于是否捕捉了异常。如果捕捉了异常,那么就不回滚,否则回滚。 + // 当前方法存在事务时,子方法加入在嵌套事务执行。当父方法事务回滚时,子方法事务也跟着回滚。 + // 当子方法事务发送回滚时,父事务是否回滚取决于是否捕捉了异常。如果捕捉了异常,那么就不回滚,否则回滚。 NESTED(TransactionDefinition.PROPAGATION_NESTED); } ``` @@ -79,32 +82,30 @@ public enum Propagation { 声明式事务是建立在 AOP 之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况“提交”或者“回滚”事务。 - ```java @Transactional public void methodA(){ - jdbcTemplate.batchUpdate(updateSql, params); - methodB(); -} + jdbcTemplate.batchUpdate(updateSql,params); + methodB(); + } // 传播行为配置为 - 方式2,不使用当前事务,独立一个新事务 @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB(){ - jdbcTemplate.batchUpdate(updateSql, params); -} + jdbcTemplate.batchUpdate(updateSql,params); + } ``` ## 5.2. 编程式 -编程式事务使用 TransactionTemplate 或者直接使用底层的 PlatformTransactionManager 实现事务。 对于编程式事务 Spring 比较推荐使用 +编程式事务使用 TransactionTemplate 或者直接使用底层的 PlatformTransactionManager 实现事务。 +对于编程式事务 Spring 比较推荐使用 TransactionTemplate 来对事务进行管理。 其中 TransactionTemplate 的 execute 能接受两种类型参数执行事务,分别为: - -```shell +```Java TransactionCallback(): 执行事务且可以返回一个值。 TransactionCallbackWithoutResult(): 执行事务没有返回值。 - ``` # 6. 事务的回滚 @@ -123,21 +124,18 @@ TransactionTemplate 来对事务进行管理。 # 7. 事务的失效 ## 7.1. 只能外部类来调用 -若同一类中的其他没有 @Transactional 注解的方法内部调用有 @Transactional 注解的方法,有 @Transactional 注解的方法的事务会失效。 +若同一类中的其他没有 @Transactional 注解的方法内部调用有 @Transactional 注解的方法,有 @Transactional 注解的方法的事务会失效。 这是由于 Spring AOP 代理的原因造成的,因为只有当 @Transactional 注解的方法在类以外被调用的时候,Spring 事务管理才生效。 - 另外,如果直接调用,不通过对象调用,也是会失效的。因为 Spring 事务是通过 AOP 实现的。 ## 7.2. 只能public + @Transactional 注解只有作用到 public 方法上事务才生效。被 @Transactional 注解的方法所在的类必须被 Spring 管理。 ## 7.3. 底层数据库要支持 -底层使用的数据库必须支持事务机制,否则不生效。 - - - +底层使用的数据库必须支持事务机制,否则不生效。 # 8. 参考文献 diff --git a/docs/test/Jmeter.md b/docs/test/Jmeter Mac.md similarity index 97% rename from docs/test/Jmeter.md rename to docs/test/Jmeter Mac.md index 4cf76f1..9d6c9f2 100644 --- a/docs/test/Jmeter.md +++ b/docs/test/Jmeter Mac.md @@ -1,6 +1,6 @@ --- layout: default -title: Jmeter +title: Jmeter Mac parent: Test --- diff --git "a/docs/test/Jmeter\347\220\206\350\256\272.md" "b/docs/test/Jmeter\347\220\206\350\256\272.md" index afb5b15..6d3d194 100644 --- "a/docs/test/Jmeter\347\220\206\350\256\272.md" +++ "b/docs/test/Jmeter\347\220\206\350\256\272.md" @@ -23,7 +23,8 @@ JMeter通过断言来验证服务器返回的结果是否符合预期,如果 ## 什么是Jmeter测试片段? ```text -Jmeter测试片段是一个特殊的线程组,它在测试计划中与线程组处于同一层级。与线程组不同的是,测试片段不会执行,它只有当作为模块控制器或者被控制器引用时才会被执行。 +Jmeter测试片段是一个特殊的线程组,它在测试计划中与线程组处于同一层级。与线程组不同的是,测试片段不会执行, +它只有当作为模块控制器或者被控制器引用时才会被执行。 测试片段的应用场景主要包括: @@ -36,13 +37,16 @@ Jmeter测试片段是一个特殊的线程组,它在测试计划中与线程 ## Meter中的预处理器和后处理器。 ```text -预处理器(Preprocessor)和后处理器(Postprocessor)是JMeter中的两种重要元件,它们分别在取样器(Sampler)之前和之后执行,用于处理请求和响应数据。 +预处理器(Preprocessor)和后处理器(Postprocessor)是JMeter中的两种重要元件, +它们分别在取样器(Sampler)之前和之后执行,用于处理请求和响应数据。 -预处理器在取样器之前执行,主要用于对请求进行预处理,如设置请求参数、添加请求头、URL重写等。常见的预处理器包括HTTP URL重写修饰符、 +预处理器在取样器之前执行,主要用于对请求进行预处理, +如设置请求参数、添加请求头、URL重写等。常见的预处理器包括HTTP URL重写修饰符、 HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以帮助模拟更真实的请求场景,提高测试的准确性和可靠性。 后处理器在取样器之后执行,主要用于对响应数据进行处理,如提取响应数据、验证响应结果等。 -常见的后处理器包括正则表达式提取器、XPath提取器等。后处理器的使用可以帮助提取响应数据中的关键信息,并进行断言和监听,以便对响应结果进行验证和分析。 +常见的后处理器包括正则表达式提取器、XPath提取器等。后处理器的使用可以帮助提取响应数据中的关键信息, +并进行断言和监听,以便对响应结果进行验证和分析。 总之,预处理器和后处理器是JMeter中非常重要的元件,它们的使用可以帮助模拟更真实的请求场景,提高测试的准确性和可靠性, 同时也可以对响应数据进行处理和分析,以便更好地评估系统的性能和稳定性。 @@ -57,11 +61,13 @@ HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以 在终极线程组中,可以设置启动的线程数量、延迟时间、线程启动时间、压力满足之后持续运行的时间和释放掉压力需要的时间等参数。 接下来,添加同步计时器。在测试计划中右键单击,选择添加定时器,然后选择Synchronizing Timer。 -在同步计时器中,可以设置等待一定数量的线程启动后再开始执行取样器的时间。这样,就可以模拟出在某一瞬间或者多个频次下用户数和压力陡然增加的场景。 +在同步计时器中,可以设置等待一定数量的线程启动后再开始执行取样器的时间。 +这样,就可以模拟出在某一瞬间或者多个频次下用户数和压力陡然增加的场景。 最后,添加取样器和监听器。根据实际需求,选择适当的取样器和监听器,并按照测试计划进行配置。 -需要注意的是,在使用非GUI模式执行测试时,需要使用命令行参数“-n”来运行JMeter,并且需要在命令行中指定测试脚本文件和结果文件。 +需要注意的是,在使用非GUI模式执行测试时,需要使用命令行参数“-n”来运行JMeter, +并且需要在命令行中指定测试脚本文件和结果文件。 同时,在加载期间,测试不使用“查看结果树”或“查看表中的结果”监听器,仅在脚本编写阶段使用它们。 总之,通过使用终极线程组和同步计时器,可以在JMeter中模拟出尖峰测试的场景,以便评估系统在高并发下的性能和稳定性。 @@ -70,7 +76,9 @@ HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以 ## 什么是分布式负载测试?如何实现? ```text -分布式负载测试是一种性能测试方法,它通过多台计算机同时产生负载来模拟大量用户同时访问系统的场景,以测试系统的性能和稳定性。在分布式负载测试中,每台计算机都作为一个负载生成器,向被测系统发送请求,以检测系统在高并发、大数据量情况下的表现。 +分布式负载测试是一种性能测试方法,它通过多台计算机同时产生负载来模拟大量用户同时访问系统的场景, +以测试系统的性能和稳定性。在分布式负载测试中,每台计算机都作为一个负载生成器, +向被测系统发送请求,以检测系统在高并发、大数据量情况下的表现。 要实现分布式负载测试,通常需要以下几个步骤: @@ -85,30 +93,39 @@ HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以 合理分配测试任务,确保每台计算机都能充分利用其资源,避免资源浪费或过载。 监控测试过程中的各项指标,及时发现并解决问题,确保测试的顺利进行。 对测试结果进行全面分析,找出系统的瓶颈和潜在问题,为系统优化提供依据。 -总之,分布式负载测试是一种有效的性能测试方法,可以帮助开发人员和测试人员更好地了解系统在高并发、大数据量情况下的性能和稳定性表现,为系统优化和部署提供有力支持。 +总之,分布式负载测试是一种有效的性能测试方法,可以帮助开发人员和测试人员更好地了解系统在高并发、 +大数据量情况下的性能和稳定性表现,为系统优化和部署提供有力支持。 ``` ## 解释JMeter中的配置元件、前置处理器、计时器、取样器、后置处理器、断言和监听器的作用和执行顺序 - ```text -配置元件(Config Element):用于配置测试计划中的一些参数或设置,例如用户定义的变量、CSV Data Set Config等。配置元件在测试计划中只会被执行一次。 +配置元件(Config Element):用于配置测试计划中的一些参数或设置,例如用户定义的变量、 +CSV Data Set Config等。配置元件在测试计划中只会被执行一次。 -前置处理器(Pre-Processor):在取样器之前执行,用于对请求进行预处理,如添加请求头、URL重写等。前置处理器可以在单个的请求中添加、修改或删除请求/响应数据。 +前置处理器(Pre-Processor):在取样器之前执行,用于对请求进行预处理,如添加请求头、URL重写等。 +前置处理器可以在单个的请求中添加、修改或删除请求/响应数据。 -计时器(Timer):用于在取样器之间设置延迟,模拟真实用户之间的操作间隔。计时器会随机生成一个时间间隔,以模拟用户的实际操作。 +计时器(Timer):用于在取样器之间设置延迟,模拟真实用户之间的操作间隔。 +计时器会随机生成一个时间间隔,以模拟用户的实际操作。 -取样器(Sampler):用于模拟用户对服务器的请求,并记录服务器的响应结果。取样器会发送请求并等待服务器的响应,然后返回响应结果。 +取样器(Sampler):用于模拟用户对服务器的请求,并记录服务器的响应结果。 +取样器会发送请求并等待服务器的响应,然后返回响应结果。 -后置处理器(Post-Processor):在取样器之后执行,用于对响应数据进行处理,如提取响应数据、验证响应结果等。后置处理器可以在单个的响应中添加、修改或删除数据。 +后置处理器(Post-Processor):在取样器之后执行,用于对响应数据进行处理, +如提取响应数据、验证响应结果等。后置处理器可以在单个的响应中添加、修改或删除数据。 -断言(Assertion):用于验证服务器的响应是否符合预期结果。断言可以对响应状态、响应时间、响应内容等进行断言,以判断测试是否通过。 +断言(Assertion):用于验证服务器的响应是否符合预期结果。 +断言可以对响应状态、响应时间、响应内容等进行断言,以判断测试是否通过。 -监听器(Listener):用于显示和记录测试结果。监听器可以显示测试过程中的各种数据,如响应时间、吞吐量、错误率等指标,并将测试结果保存到文件或图形化界面中。 +监听器(Listener):用于显示和记录测试结果。监听器可以显示测试过程中的各种数据, +如响应时间、吞吐量、错误率等指标,并将测试结果保存到文件或图形化界面中。 -执行顺序:在JMeter中,测试计划中的元件按照一定的顺序执行。首先执行配置元件,然后执行前置处理器,接着执行计时器,然后执行取样器,接着执行后置处理器,最后执行断言和监听器。 +执行顺序:在JMeter中,测试计划中的元件按照一定的顺序执行。首先执行配置元件,然后执行前置处理器, +接着执行计时器,然后执行取样器,接着执行后置处理器,最后执行断言和监听器。 ``` + ## 如何在JMeter中减少资源需求? ```text @@ -117,7 +134,8 @@ HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以 1. 减少线程数:降低线程数可以减少对CPU和内存的需求。根据实际情况,合理设置线程数,避免过多线程导致系统资源耗尽。 2. 调整优先级:JMeter中的线程按照优先级进行调度,可以将较低优先级的线程数减少,从而减少资源占用。 -3. 使用合适的数据驱动方式:JMeter支持多种数据驱动方式,如CSV Data Set Config、JDBC Connection Configuration等。根据实际情况选择合适的数据驱动方式,可以减少资源占用。 +3. 使用合适的数据驱动方式:JMeter支持多种数据驱动方式,如CSV Data Set Config、JDBC Connection Configuration等。 + 根据实际情况选择合适的数据驱动方式,可以减少资源占用。 4. 禁用不必要的监听器:监听器会占用一定的资源。在测试过程中,可以根据需要选择监听器,避免不必要的资源占用。 5. 禁用日志记录:在测试过程中,可以通过禁用日志记录来减少资源占用。不过需要注意的是,禁用日志记录可能会影响问题排查和测试结果分析。 6. 优化JMeter设置:可以通过调整JMeter的配置参数来减少资源占用,例如设置缓存大小、最大连接数等。具体可参考JMeter官方文档和社区论坛。 @@ -126,15 +144,18 @@ HTTP用户参数修饰符、HTML链接解析器等。预处理器的使用可以 总之,在JMeter中减少资源需求需要根据实际情况进行综合考虑,合理配置测试计划和参数,以达到更好的测试效果和资源利用率。 ``` - ## JMeter中的变量和函数的使用 ```text JMeter中的变量和函数的使用非常灵活和强大,它们可以帮助测试人员更好地模拟用户行为、处理测试数据和验证测试结果。 -变量在JMeter中用于存储静态或动态的值,可以在测试计划中的任何地方引用和使用。用户可以通过用户定义的变量来设置和引用变量,也可以使用内置的变量,如${__time(格式)},用于获取当前时间。需要注意的是,当测试计划中引用了未定义的变量时,JMeter并不会报告错误信息,而是将引用的值视为引用本身。 +变量在JMeter中用于存储静态或动态的值,可以在测试计划中的任何地方引用和使用。用户可以通过用户定义的变量来设置和引用变量, +也可以使用内置的变量,如${__time(格式)},用于获取当前时间。需要注意的是, +当测试计划中引用了未定义的变量时,JMeter并不会报告错误信息,而是将引用的值视为引用本身。 -函数在JMeter中用于执行各种操作,如处理请求和响应数据、生成随机数、计算结果等。JMeter提供了大量的内置函数,如${__intSum(a,b)}用于计算两个整数的和,${__Random(min,max)}用于生成指定范围内的随机数等。测试人员可以使用函数助手对话框来选择和配置函数,并为其提供参数值。 +函数在JMeter中用于执行各种操作,如处理请求和响应数据、生成随机数、计算结果等。JMeter提供了大量的内置函数, +如${__intSum(a,b)}用于计算两个整数的和,${__Random(min,max)}用于生成指定范围内的随机数等。 +测试人员可以使用函数助手对话框来选择和配置函数,并为其提供参数值。 在使用变量和函数时,需要注意以下几点: @@ -154,12 +175,15 @@ JMeter中的变量和函数的使用非常灵活和强大,它们可以帮助 通过录制来捕获脚本是JMeter中一种常用的方法,可以方便地获取接口内容。以下是录制脚本的步骤: 1. 创建一个线程组(右键点击“测试计划”——>“添加”——>“线程组”)。 -2. 创建一个http代理服务器(右键点击“测试计划”——>“添加”——>“非测试元件”——>”http代理服务器”),并配置如下:在“HTTP代理服务器”中设置端口号(例如:8080),并启动录制。 +2. 创建一个http代理服务器(右键点击“测试计划”——>“添加”——>“非测试元件”——>”http代理服务器”), + 并配置如下:在“HTTP代理服务器”中设置端口号(例如:8080),并启动录制。 3. 设置浏览器的代理服务器,将代理服务器设置为127.0.0.1和之前设置的端口号(例如:8080)。 4. 在浏览器中输入需要录制的接口网址,然后进行操作。在录制过程中,JMeter会捕获所有通过代理服务器发出的请求和响应。 -5. 录制完成后,可以在JMeter中查看和修改脚本。可以通过右键点击“测试计划”——>“添加”——>“取样器”——>“HTTP请求”来添加新的请求,并设置请求参数和头信息等。也可以使用断言和监听器来验证测试结果。 +5. 录制完成后,可以在JMeter中查看和修改脚本。可以通过右键点击“测试计划”——>“添加”——>“取样器”——>“HTTP请求”来添加新的请求, + 并设置请求参数和头信息等。也可以使用断言和监听器来验证测试结果。 -需要注意的是,在录制过程中可能会录制到不必要的请求和数据,需要手动删除或修改脚本。另外,如果接口需要登录等操作,需要在录制前先进行相应的操作,否则无法录制到正确的脚本内容。 +需要注意的是,在录制过程中可能会录制到不必要的请求和数据,需要手动删除或修改脚本。 +另外,如果接口需要登录等操作,需要在录制前先进行相应的操作,否则无法录制到正确的脚本内容。 总之,通过录制来捕获脚本是一种方便快捷的方法,可以帮助测试人员快速获取接口内容,并进行测试和验证。 ``` @@ -169,15 +193,19 @@ JMeter中的变量和函数的使用非常灵活和强大,它们可以帮助 ```text 在JMeter中,Testplan元件的执行顺序如下: -1. 配置元件(Config Elements):配置元件在Testplan中只会被执行一次。它们主要用于配置测试计划中的一些参数或设置,例如用户定义的变量、CSV Data Set Config等。 +1. 配置元件(Config Elements):配置元件在Testplan中只会被执行一次。它们主要用于配置测试计划中的一些参数或设置, + 例如用户定义的变量、CSV Data Set Config等。 2. 前置处理器(Pre-Processors):前置处理器在取样器之前执行,用于对请求进行预处理,如添加请求头、URL重写等。 3. 计时器(Timer):计时器用于在取样器之间设置延迟,模拟真实用户之间的操作间隔。 4. 取样器(Sampler):取样器用于模拟用户对服务器的请求,并记录服务器的响应结果。取样器会发送请求并等待服务器的响应,然后返回响应结果。 5. 后置处理器(Post-Processors):后置处理器在取样器之后执行,用于对响应数据进行处理,如提取响应数据、验证响应结果等。 6. 断言(Assertions):断言用于验证服务器的响应是否符合预期结果。断言可以对响应状态、响应时间、响应内容等进行断言,以判断测试是否通过。 -7. 监听器(Listeners):监听器用于显示和记录测试结果。监听器可以显示测试过程中的各种数据,如响应时间、吞吐量、错误率等指标,并将测试结果保存到文件或图形化界面中。 +7. 监听器(Listeners):监听器用于显示和记录测试结果。监听器可以显示测试过程中的各种数据, + 如响应时间、吞吐量、错误率等指标,并将测试结果保存到文件或图形化界面中。 -需要注意的是,在同一作用域范围内有多个同一类型的元件时,它们将按照在testplan中的上下顺序依次执行。同时,由于JMeter通过鼠标拖拽来随意改变元件之间的顺序以及元件的父子关系,因此元件的相对位置、父子关系以及元件本身的类型决定了testplan中各元件的执行顺序。 +需要注意的是,在同一作用域范围内有多个同一类型的元件时,它们将按照在testplan中的上下顺序依次执行。 +同时,由于JMeter通过鼠标拖拽来随意改变元件之间的顺序以及元件的父子关系, +因此元件的相对位置、父子关系以及元件本身的类型决定了testplan中各元件的执行顺序。 总之,了解Testplan元件的执行顺序对于正确配置和组织测试计划非常重要,可以帮助测试人员更好地模拟用户行为、处理测试数据和验证测试结果。 ``` @@ -186,16 +214,21 @@ JMeter中的变量和函数的使用非常灵活和强大,它们可以帮助 JMeter中的监听器主要用于显示和记录测试结果,包括以下几种: -1. **查看结果树监听器(View Results Tree Listener)**:这个监听器以树形结构显示每次请求的详细结果,包括请求的详细信息、响应时间、状态代码等。这是最常用的监听器之一,可以帮助测试人员查看和分析每次请求的详细信息。 -2. **汇总报告监听器(Summary Report Listener)**:这个监听器以表格形式显示测试的汇总结果,包括响应时间、状态代码、请求数、错误数等。这个监听器适合在测试结束后查看整体测试结果。 -3. **图形结果监听器(Graph Results Listener)**:这个监听器以图形方式显示测试结果,包括响应时间、吞吐量等指标。通过图形方式,可以更直观地查看和分析测试结果。 -4. **响应时间-线程监听器(Response Time vs Threads Listener)**:这个监听器以图形方式显示响应时间与线程的关系,可以分析在多线程情况下系统的性能表现。 +1. **查看结果树监听器(View Results Tree Listener)**:这个监听器以树形结构显示每次请求的详细结果, + 包括请求的详细信息、响应时间、状态代码等。这是最常用的监听器之一,可以帮助测试人员查看和分析每次请求的详细信息。 +2. **汇总报告监听器(Summary Report Listener)**:这个监听器以表格形式显示测试的汇总结果,包括响应时间、状态代码、请求数、错误数等。 + 这个监听器适合在测试结束后查看整体测试结果。 +3. **图形结果监听器(Graph Results Listener)**:这个监听器以图形方式显示测试结果,包括响应时间、吞吐量等指标。通过图形方式, + 可以更直观地查看和分析测试结果。 +4. **响应时间-线程监听器(Response Time vs Threads Listener)**:这个监听器以图形方式显示响应时间与线程的关系, + 可以分析在多线程情况下系统的性能表现。 5. **Active Threads Over Time 监听器**:这个监听器以图形方式显示活动线程数随时间的变化情况,可以分析系统的并发处理能力。 6. **Response Time Distribution 监听器**:这个监听器以柱状图方式显示响应时间的分布情况,可以分析系统在不同响应时间下的表现。 7. **Response Times Percentiles 监听器**:这个监听器以图形方式显示响应时间的百分比分布情况,可以分析系统在不同响应时间下的表现。 8. **Assertions 监听器**:这个监听器用于查看断言结果,可以验证测试是否通过。 9. **Assertions Visualizer 监听器**:这个监听器可以以图形方式显示断言结果,方便测试人员查看和分析断言结果。 -10. **生成总结报告监听器(Generate Summary Results Listener)**:这个监听器可以生成一个HTML格式的测试总结报告,方便测试人员分享和查看测试结果。 +10. **生成总结报告监听器(Generate Summary Results Listener)**:这个监听器可以生成一个HTML格式的测试总结报告, + 方便测试人员分享和查看测试结果。 这些监听器各有特点和适用场景,可以根据实际需求选择合适的监听器来查看和分析测试结果。 @@ -204,24 +237,26 @@ JMeter中的监听器主要用于显示和记录测试结果,包括以下几 ```text Jmeter中的循环控制器主要有两种:循环控制器(Loop Controller)和While Controller。 -循环控制器用于控制测试计划中的循环执行次数。通过设置循环次数或使用变量,可以控制其子节点运行的次数。如果设置了线程组的循环次数和循环控制器的循环次数,那么循环控制器的子节点运行的次数为两个数值相乘的结果。 +循环控制器用于控制测试计划中的循环执行次数。通过设置循环次数或使用变量,可以控制其子节点运行的次数。 +如果设置了线程组的循环次数和循环控制器的循环次数,那么循环控制器的子节点运行的次数为两个数值相乘的结果。 While Controller则是在满足条件的情况下,循环执行某个步骤。 包含控制器(Include Controller)用于包含另一个测试计划文件。当选中包含控制器时,它会将另一个测试计划文件添加到当前测试计划中。 - -以上内容仅供参考,如需更多关于JMeter中循环控制器和包含控制器的信息,建议查阅JMeter官方文档或咨询相关技术人员。 ``` - ## 解释JMeter中的BeanShell Listener。 ```text -JMeter中的BeanShell Listener是一个监听器,用于在测试执行过程中对测试结果进行更深入的分析和操作。BeanShell是一种基于Java的脚本语言,具有动态脚本的功能,可以用于编写复杂的逻辑和操作。 +JMeter中的BeanShell Listener是一个监听器,用于在测试执行过程中对测试结果进行更深入的分析和操作。 +BeanShell是一种基于Java的脚本语言,具有动态脚本的功能,可以用于编写复杂的逻辑和操作。 -BeanShell Listener通过BeanShell脚本实现对测试结果的进一步处理。它允许用户编写自己的脚本来处理和转换JMeter中的测试结果。用户可以使用BeanShell的语法和Java的API,对测试结果进行自定义操作和解析。 +BeanShell Listener通过BeanShell脚本实现对测试结果的进一步处理。它允许用户编写自己的脚本来处理和转换JMeter中的测试结果。 +用户可以使用BeanShell的语法和Java的API,对测试结果进行自定义操作和解析。 -使用BeanShell Listener,用户可以根据测试结果进行各种自定义操作,例如提取特定字段的值、计算统计指标、对结果进行条件判断等。通过编写BeanShell脚本,用户可以灵活地处理和解析测试结果,以满足特定的需求。 +使用BeanShell Listener,用户可以根据测试结果进行各种自定义操作,例如提取特定字段的值、计算统计指标、对结果进行条件判断等。 +通过编写BeanShell脚本,用户可以灵活地处理和解析测试结果,以满足特定的需求。 -BeanShell Listener的使用需要一定的脚本编写能力,但通过编写简单的脚本,用户可以实现对测试结果的自定义处理和操作,从而更好地分析和评估测试结果。 +BeanShell Listener的使用需要一定的脚本编写能力,但通过编写简单的脚本, +用户可以实现对测试结果的自定义处理和操作,从而更好地分析和评估测试结果。 ``` \ No newline at end of file diff --git a/docs/test/Selenium.md b/docs/test/Selenium.md index fea228b..cbced6d 100644 --- a/docs/test/Selenium.md +++ b/docs/test/Selenium.md @@ -7,29 +7,44 @@ parent: Test ## 1. 什么是Selenium,以及它在自动化测试中的作用是什么? ```text -Selenium是一个用于Web应用程序测试的工具,它可以模拟真实用户在浏览器中的操作,从而进行自动化测试。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,因此可以测试实际用户可能进行的各种操作。 +Selenium是一个用于Web应用程序测试的工具,它可以模拟真实用户在浏览器中的操作,从而进行自动化测试。 +Selenium测试直接运行在浏览器中,就像真正的用户在操作一样,因此可以测试实际用户可能进行的各种操作。 Selenium在自动化测试中的作用主要体现在以下几个方面: 测试与浏览器的兼容性:使用Selenium可以测试应用程序在不同浏览器和操作系统上的表现,以确保跨平台的兼容性。 -测试系统功能:Selenium可以用来执行回归测试,通过编写自动化测试脚本来检验软件功能和用户需求是否得到满足。这有助于确保软件在添加新功能或修改现有功能时不会破坏已有的功能。 -提高测试效率和质量:自动化测试可以消除人为因素的影响,减少测试过程中的错误和失误,从而提高测试的准确性和可靠性。同时,自动化测试可以节省大量的人力、物力和时间成本,特别是在长期和重复的测试环节中更为显著。 -支持多种编程语言和框架:Selenium支持多种编程语言,如Java、Python、C#等,方便开发人员使用自己熟悉的语言进行测试开发。此外,Selenium还提供了丰富的API和框架支持,使得测试人员可以更加灵活地编写测试脚本和执行测试任务。 + +测试系统功能:Selenium可以用来执行回归测试,通过编写自动化测试脚本来检验软件功能和用户需求是否得到满足。 +这有助于确保软件在添加新功能或修改现有功能时不会破坏已有的功能。 + +提高测试效率和质量:自动化测试可以消除人为因素的影响,减少测试过程中的错误和失误,从而提高测试的准确性和可靠性。 +同时,自动化测试可以节省大量的人力、物力和时间成本,特别是在长期和重复的测试环节中更为显著。 + +支持多种编程语言和框架:Selenium支持多种编程语言,如Java、Python、C#等, +方便开发人员使用自己熟悉的语言进行测试开发。 +此外,Selenium还提供了丰富的API和框架支持,使得测试人员可以更加灵活地编写测试脚本和执行测试任务。 ``` ## 2. 你能描述一下Selenium的组件及其各自的功能吗?例如:Selenium IDE、Selenium WebDriver、Selenium Grid。 ```text - Selenium IDE (集成开发环境) -功能:这是一个嵌入到Firefox浏览器中的插件,提供了简单的浏览器操作录制与回放功能。它主要用于快速创建bug及重现脚本,并且可以导出为多种语言(如Java、Python、Ruby、C#等)的自动化测试脚本。这对于初学者或者快速原型设计非常有用。 +功能:这是一个嵌入到Firefox浏览器中的插件,提供了简单的浏览器操作录制与回放功能。 +它主要用于快速创建bug及重现脚本, +并且可以导出为多种语言(如Java、Python、Ruby、C#等)的自动化测试脚本。 +这对于初学者或者快速原型设计非常有用。 Selenium WebDriver -功能:WebDriver是Selenium的核心组件,它是一个浏览器自动化框架。它接受命令并将它们发送到浏览器,通过特定于浏览器的驱动程序实现与浏览器的直接通信和控制。WebDriver支持各种编程语言,如Java、C#、PHP、Python、Perl、Ruby等,使得开发人员可以根据自己的需求选择合适的语言编写测试脚本。 +功能:WebDriver是Selenium的核心组件,它是一个浏览器自动化框架。 +它接受命令并将它们发送到浏览器,通过特定于浏览器的驱动程序实现与浏览器的直接通信和控制。 +WebDriver支持各种编程语言,如Java、C#、PHP、Python、Perl、Ruby等, +使得开发人员可以根据自己的需求选择合适的语言编写测试脚本。 Selenium Grid -功能:Grid是Selenium的测试辅助工具,主要用于分布式测试。它允许你在多台计算机上并行执行多个测试任务,从而显著提高测试效率。通过Grid,你可以轻松地对多种浏览器/操作系统组合运行测试,并从一个中心点管理多个测试环境。 +功能:Grid是Selenium的测试辅助工具,主要用于分布式测试。 +它允许你在多台计算机上并行执行多个测试任务,从而显著提高测试效率。 +通过Grid,你可以轻松地对多种浏览器/操作系统组合运行测试,并从一个中心点管理多个测试环境。 ``` ![selenium-components.png](img%2Fselenium-components.png) @@ -37,13 +52,25 @@ Selenium Grid ## 3. 你如何理解Selenium WebDriver的工作原理? ```text -具体来说,当测试脚本启动WebDriver时,它会创建一个与指定浏览器的会话(session)。这个会话将作为WebDriver与浏览器之间的通信桥梁。WebDriver向浏览器发送HTTP请求,这些请求通过浏览器驱动程序(如ChromeDriver、GeckoDriver等)转换为浏览器可以理解的命令。浏览器执行这些命令后,将执行结果返回给浏览器驱动程序,再由驱动程序将结果反馈给WebDriver。最终,WebDriver将结果返回给测试脚本。 - -在这个过程中,WebDriver充当了一个代理的角色,它负责将测试脚本的命令传递给浏览器,并将浏览器的响应传递回测试脚本。这种基于HTTP协议的通信方式使得WebDriver可以与多种编程语言和框架集成,从而实现对Web应用程序的自动化测试。 - -需要注意的是,WebDriver与浏览器之间的通信是基于特定的WebDriver协议进行的。这个协议定义了一组标准的HTTP请求和响应格式,以及用于操作浏览器的各种命令。因此,不同的浏览器需要实现各自对应的WebDriver协议才能与WebDriver进行通信。这也是为什么在使用WebDriver时需要下载与浏览器版本相匹配的驱动程序的原因。 - -总的来说,Selenium WebDriver的工作原理是通过与浏览器驱动程序的直接通信来控制浏览器行为,实现Web应用程序的自动化测试。它基于HTTP协议进行通信,可以支持多种编程语言和框架集成,具有高度的灵活性和可扩展性。 +具体来说,当测试脚本启动WebDriver时,它会创建一个与指定浏览器的会话(session)。 +这个会话将作为WebDriver与浏览器之间的通信桥梁。WebDriver向浏览器发送HTTP请求, +这些请求通过浏览器驱动程序(如ChromeDriver、GeckoDriver等)转换为浏览器可以理解的命令。 +浏览器执行这些命令后,将执行结果返回给浏览器驱动程序,再由驱动程序将结果反馈给WebDriver。 +最终,WebDriver将结果返回给测试脚本。 + +在这个过程中,WebDriver充当了一个代理的角色,它负责将测试脚本的命令传递给浏览器, +并将浏览器的响应传递回测试脚本。这种基于HTTP协议的通信方式使得WebDriver +可以与多种编程语言和框架集成, +从而实现对Web应用程序的自动化测试。 + +需要注意的是,WebDriver与浏览器之间的通信是基于特定的WebDriver协议进行的。 +这个协议定义了一组标准的HTTP请求和响应格式,以及用于操作浏览器的各种命令。 +因此,不同的浏览器需要实现各自对应的WebDriver协议才能与WebDriver进行通信。 +这也是为什么在使用WebDriver时需要下载与浏览器版本相匹配的驱动程序的原因。 + +总的来说,Selenium WebDriver的工作原理是通过与浏览器驱动程序的直接通信来控制浏览器行为, +实现Web应用程序的自动化测试。它基于HTTP协议进行通信, +可以支持多种编程语言和框架集成,具有高度的灵活性和可扩展性。 ``` ## 4. 你如何在Selenium中定位页面元素?请列举一些常用的元素定位方法。 @@ -105,14 +132,17 @@ Selenium Grid ``` 如果你想找到页面上所有匹配的元素,而不是第一个匹配的元素,你可以使用`findElements` -(注意是复数)方法,例如`findElements(By.className("class_name"))`,这将返回一个`List`,你可以遍历这个列表来操作每个元素。 +(注意是复数)方法,例如`findElements(By.className("class_name"))`,这将返回一个`List`, +你可以遍历这个列表来操作每个元素。 请注意,在使用这些方法之前,你需要确保已经创建了一个WebDriver实例(如`WebDriver driver = new ChromeDriver();` )并且已经导航到了相应的页面(如`driver.get("http://example.com");`)。 ## 5. 如果页面上的元素动态加载,你如何在Selenium中处理这种情况? -当页面上的元素是动态加载的,即这些元素不是在页面初始加载时就存在的,而是在某些用户交互或异步请求后才出现的,使用Selenium进行自动化测试时需要特别处理。以下是一些处理动态加载元素的方法: +当页面上的元素是动态加载的,即这些元素不是在页面初始加载时就存在的, +而是在某些用户交互或异步请求后才出现的,使用Selenium进行自动化测试时需要特别处理。 +以下是一些处理动态加载元素的方法: 1. **等待机制**: Selenium提供了几种等待机制,用于确保动态元素在尝试与之交互之前已经完全加载。 @@ -129,7 +159,8 @@ Selenium Grid ``` 2. **动态定位**: - 如果元素的属性(如ID、类名)在动态加载过程中会发生变化,你需要构建能够适应这些变化的定位策略。例如,使用XPath或CSS选择器定位具有特定文本或相对位置不变的元素。 + 如果元素的属性(如ID、类名)在动态加载过程中会发生变化,你需要构建能够适应这些变化的定位策略。 +3. 例如,使用XPath或CSS选择器定位具有特定文本或相对位置不变的元素。 3. **JavaScript执行**: 在某些情况下,你可能需要借助JavaScript来直接操作DOM,特别是当Selenium的常规方法不起作用时。 @@ -148,18 +179,23 @@ Selenium Grid ``` 6. **增加延迟**: - 虽然不推荐仅依赖固定的延迟来处理动态内容(因为这会导致测试变得缓慢且不稳定),但在某些情况下,添加小的延迟可能是必要的,以确保元素有足够的时间加载。 + 虽然不推荐仅依赖固定的延迟来处理动态内容(因为这会导致测试变得缓慢且不稳定), + 但在某些情况下,添加小的延迟可能是必要的,以确保元素有足够的时间加载。 -在处理动态加载的元素时,最重要的是要确保你的自动化测试脚本具有足够的健壮性和容错性,能够处理各种可能的加载延迟和异常情况。使用显式等待和动态定位策略是实现这一目标的关键。 +在处理动态加载的元素时,最重要的是要确保你的自动化测试脚本具有足够的健壮性和容错性, +能够处理各种可能的加载延迟和异常情况。使用显式等待和动态定位策略是实现这一目标的关键。 ## 6. 当一个元素在页面上不可见时,Selenium能否与之交互?如果不能,你通常会如何处理? -当一个元素在页面上不可见时,Selenium默认情况下是无法与之交互的。这是因为Selenium试图模拟真实用户的行为,而真实用户无法与不可见的元素进行交互。然而,有些情况下,你可能需要与这些不可见元素进行交互,以完成自动化测试的任务。 +当一个元素在页面上不可见时,Selenium默认情况下是无法与之交互的。这是因为Selenium试图模拟真实用户的行为, +而真实用户无法与不可见的元素进行交互。然而,有些情况下,你可能需要与这些不可见元素进行交互,以完成自动化测试的任务。 处理不可见元素的方法有几种: 1. **使用JavaScript执行器**: - 你可以使用Selenium的JavaScript执行器来与不可见元素交互。通过执行JavaScript代码,你可以绕过浏览器的可见性限制,直接操作DOM元素。例如,你可以使用JavaScript来点击一个不可见的按钮或输入文本到一个不可见的输入框。 + 你可以使用Selenium的JavaScript执行器来与不可见元素交互。通过执行JavaScript代码, + 你可以绕过浏览器的可见性限制,直接操作DOM元素。 + 例如,你可以使用JavaScript来点击一个不可见的按钮或输入文本到一个不可见的输入框。 ```java JavascriptExecutor jsExecutor = (JavascriptExecutor) driver; @@ -167,7 +203,8 @@ Selenium Grid ``` 2. **修改元素的可见性**: - 如果可能的话,你可以通过执行JavaScript来修改元素的可见性属性,使其变得可见,然后使用Selenium的正常方法与之交互。例如,你可以改变一个元素的CSS属性`display` + 如果可能的话,你可以通过执行JavaScript来修改元素的可见性属性,使其变得可见, + 然后使用Selenium的正常方法与之交互。例如,你可以改变一个元素的CSS属性`display` 或`visibility`。 ```java @@ -194,10 +231,12 @@ Selenium Grid 或`z-index`的设置。在这种情况下,你可能需要更详细地检查元素的样式和布局。 6. **与开发人员沟通**: - 如果经常需要与不可见元素交互,这可能是应用程序设计的一个问题。与开发团队沟通,了解为什么元素被设置为不可见,以及是否有更好的方法来自动化测试这些功能。 + 如果经常需要与不可见元素交互,这可能是应用程序设计的一个问题。与开发团队沟通, + 了解为什么元素被设置为不可见,以及是否有更好的方法来自动化测试这些功能。 7. **考虑使用其他工具或方法**: - 在某些情况下,使用Selenium可能不是自动化特定任务的最佳选择。考虑使用其他自动化工具或方法,如直接API测试、使用应用程序的内部钩子或模拟用户输入的更低级别的方法。 + 在某些情况下,使用Selenium可能不是自动化特定任务的最佳选择。考虑使用其他自动化工具或方法, + 如直接API测试、使用应用程序的内部钩子或模拟用户输入的更低级别的方法。 ## 7. 你如何在Selenium中处理下拉菜单(select)和弹出窗口(alert)? @@ -218,7 +257,8 @@ Selenium Grid ``` 2. **使用`ExpectedConditions`和`WebDriverWait`**: - 尽管隐式等待可以处理一些简单的延迟,但对于更复杂的页面加载,最好使用显式等待。显式等待允许你为特定条件设置一个等待时间,只有满足这个条件后,代码才会继续执行。 + 尽管隐式等待可以处理一些简单的延迟,但对于更复杂的页面加载,最好使用显式等待。 + 显式等待允许你为特定条件设置一个等待时间,只有满足这个条件后,代码才会继续执行。 ```java WebDriverWait wait = new WebDriverWait(driver, 10); // 等待最多10秒 WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.id("someId"))); @@ -239,13 +279,15 @@ Selenium Grid `FluentWait`是`WebDriverWait`的一个更灵活的版本,它允许你自定义等待策略和忽略特定类型的异常。 3. **处理动态内容**: - 对于由Ajax调用或其他异步操作加载的动态内容,你可能需要等待特定的网络请求完成或某些DOM变化发生。这可以通过分析网络流量或使用JavaScript执行器来完成。 + 对于由Ajax调用或其他异步操作加载的动态内容,你可能需要等待特定的网络请求完成或某些DOM变化发生。 + 这可以通过分析网络流量或使用JavaScript执行器来完成。 4. **分页和无限滚动处理**: 如果页面使用分页或无限滚动加载内容,你需要编写逻辑来模拟用户的滚动行为,并等待新内容加载。 5. **自定义等待条件**: - 如果内置的`ExpectedConditions`不满足你的需求,你可以编写自己的等待条件。这通常涉及到使用`ExpectedCondition`接口并实现`apply()`方法。 + 如果内置的`ExpectedConditions`不满足你的需求,你可以编写自己的等待条件。这通常涉及到使用`ExpectedCondition` + 接口并实现`apply()`方法。 6. **超时处理**: 当等待时间过长时,应确保代码能够优雅地处理超时情况。可以设置超时异常的处理逻辑,如重试、记录错误或跳过测试步骤。 @@ -253,29 +295,35 @@ Selenium Grid 7. **日志和报告**: 在测试中添加详细的日志记录,以便在出现延迟或失败时能够迅速定位问题。使用测试报告工具来记录和分析失败的情况。 -记住,处理延迟的最佳实践是避免使用固定的线程睡眠(如`Thread.sleep()`),因为它不够灵活且可能导致测试执行时间过长。相反,应该使用Selenium提供的等待机制来有效地处理页面和元素的加载延迟。 +记住,处理延迟的最佳实践是避免使用固定的线程睡眠(如`Thread.sleep()` +),因为它不够灵活且可能导致测试执行时间过长。相反,应该使用Selenium提供的等待机制来有效地处理页面和元素的加载延迟。 ## 9. 你能解释一下Selenium中的隐式等待和显式等待吗?他们的区别是什么? -当然可以。在Selenium中,隐式等待(Implicit Wait)和显式等待(Explicit Wait)是两种处理元素加载延迟的机制。它们的主要区别在于等待的灵活性和应用范围。 +当然可以。在Selenium中,隐式等待(Implicit Wait)和显式等待(Explicit Wait)是两种处理元素加载延迟的机制。 +它们的主要区别在于等待的灵活性和应用范围。 ### 隐式等待(Implicit Wait) -隐式等待是设置全局的等待时间,告诉Selenium在查找页面上的元素之前等待一定的时间。如果在这个时间内元素加载出来了,那么Selenium就会继续执行后续的操作;如果超出这个时间元素仍然没有加载出来,Selenium会抛出`NoSuchElementException`异常。 +隐式等待是设置全局的等待时间,告诉Selenium在查找页面上的元素之前等待一定的时间。如果在这个时间内元素加载出来了, +那么Selenium就会继续执行后续的操作;如果超出这个时间元素仍然没有加载出来,Selenium会抛出`NoSuchElementException` +异常。 ```java -driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); +driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS); ``` 上面的代码设置了隐式等待时间为10秒。这意味着,在后续的任何元素查找操作之前,Selenium都会等待最多10秒,以便元素能够加载出来。 ### 显式等待(Explicit Wait) -显式等待则更加灵活,它允许你为特定的元素设置等待条件,而不是全局等待。你可以定义等待某个条件成立(如元素可见、可点击等),然后Selenium会不断地检查这个条件是否成立,一旦条件成立,就会立即执行后续的代码。如果超出了指定的最大等待时间,Selenium会抛出`TimeoutException`异常。 +显式等待则更加灵活,它允许你为特定的元素设置等待条件,而不是全局等待。你可以定义等待某个条件成立(如元素可见、可点击等), +然后Selenium会不断地检查这个条件是否成立,一旦条件成立,就会立即执行后续的代码。 +如果超出了指定的最大等待时间,Selenium会抛出`TimeoutException`异常。 ```java -WebDriverWait wait = new WebDriverWait(driver, 10); // 设置最大等待时间为10秒 -WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("someId"))); +WebDriverWait wait=new WebDriverWait(driver,10); // 设置最大等待时间为10秒 + WebElement element=wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("someId"))); ``` 上面的代码使用`WebDriverWait`和`ExpectedConditions`来实现显式等待。它会等待最多10秒,直到ID为`someId`的元素可见为止。 @@ -286,21 +334,23 @@ WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By 2. **等待时间**:隐式等待会在每次查找元素时都等待指定的时间,即使元素已经加载出来了。而显式等待会在条件满足时立即返回,不会浪费额外的时间。 -3. **异常处理**:隐式等待在超出等待时间后抛出`NoSuchElementException`异常。显式等待在超出等待时间后抛出`TimeoutException`异常。 +3. **异常处理**:隐式等待在超出等待时间后抛出`NoSuchElementException`异常。显式等待在超出等待时间后抛出`TimeoutException` + 异常。 4. **应用范围**:隐式等待适用于简单的页面和元素加载延迟。显式等待适用于复杂的页面和动态加载的元素,因为它提供了更多的控制和灵活性。 总的来说,显式等待在大多数情况下是更好的选择,因为它提供了更精确的控制和更高的灵活性。然而,在某些简单的场景下,隐式等待可能是一个更简洁的选择。 - ## 10. 你如何在Selenium中实现数据驱动测试? -在Selenium中实现数据驱动测试通常涉及将测试数据与测试脚本分离,使得可以使用不同的数据集多次运行相同的测试。这可以通过几种方法来实现,包括使用参数化测试、外部数据源(如CSV、Excel、数据库等)以及测试框架提供的数据驱动功能。 +在Selenium中实现数据驱动测试通常涉及将测试数据与测试脚本分离,使得可以使用不同的数据集多次运行相同的测试。这可以通过几种方法来实现, +包括使用参数化测试、外部数据源(如CSV、Excel、数据库等)以及测试框架提供的数据驱动功能。 以下是一些在Selenium中实现数据驱动测试的方法: 1. **使用测试框架的参数化功能**: - 大多数测试框架(如JUnit、TestNG、pytest等)都支持参数化测试,这意味着您可以为测试方法提供不同的输入参数。例如,在TestNG中,您可以使用`@Test`注解的`dataProvider`属性来指定一个提供测试数据的方法。 + 大多数测试框架(如JUnit、TestNG、pytest等)都支持参数化测试,这意味着您可以为测试方法提供不同的输入参数。 + 例如,在TestNG中,您可以使用`@Test` 注解的`dataProvider`属性来指定一个提供测试数据的方法。 ```java @Test(dataProvider = "testData") @@ -319,65 +369,70 @@ WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By ``` 2. **使用外部数据源**: - 您可以使用CSV、Excel、JSON、数据库等外部数据源来存储测试数据,并在测试运行时读取这些数据。例如,使用CSV文件,您可以创建一个包含多行数据的文件,每行代表一组测试数据。 + 您可以使用CSV、Excel、JSON、数据库等外部数据源来存储测试数据,并在测试运行时读取这些数据。 + 例如,使用CSV文件,您可以创建一个包含多行数据的文件,每行代表一组测试数据。 - 然后,在测试代码中,您可以编写一个方法来读取CSV文件并返回一个数据列表,这些数据可以在测试中使用。有许多库可以帮助您读取和处理这些文件格式,如Apache Commons CSV、OpenCSV、Jackson等。 + 然后,在测试代码中,您可以编写一个方法来读取CSV文件并返回一个数据列表,这些数据可以在测试中使用。 + 有许多库可以帮助您读取和处理这些文件格式,如Apache + Commons CSV、OpenCSV、Jackson等。 3. **使用环境变量或配置文件**: - 对于少量的测试数据,您也可以使用环境变量或配置文件(如properties文件)来存储它们。这种方法适用于不想使用外部文件或数据库的情况,但通常不适用于大量数据。 + 对于少量的测试数据,您也可以使用环境变量或配置文件(如properties文件)来存储它们。 + 这种方法适用于不想使用外部文件或数据库的情况,但通常不适用于大量数据。 4. **使用测试数据生成器**: - 对于需要复杂数据或大量数据的测试,您可以编写自己的测试数据生成器。这些数据生成器可以根据预定义的规则或模式创建测试数据,并在测试运行时提供给测试方法。 + 对于需要复杂数据或大量数据的测试,您可以编写自己的测试数据生成器。 + 这些数据生成器可以根据预定义的规则或模式创建测试数据,并在测试运行时提供给测试方法。 5. **结合BDD(行为驱动开发)工具**: - 使用如Cucumber、JBehave等BDD工具,您可以在特性文件(通常是Gherkin语法)中定义测试场景和示例数据。然后,这些工具会基于这些场景生成测试用例,并允许您使用不同的数据集运行它们。 + 使用如Cucumber、JBehave等BDD工具,您可以在特性文件(通常是Gherkin语法)中定义测试场景和示例数据。 + 然后,这些工具会基于这些场景生成测试用例,并允许您使用不同的数据集运行它们。 -无论选择哪种方法,关键是将测试数据与测试逻辑分离,使得更改数据集变得容易,并且可以独立地扩展和管理测试数据和测试脚本。这有助于提高测试的可维护性、可读性和可重用性。 +无论选择哪种方法,关键是将测试数据与测试逻辑分离,使得更改数据集变得容易,并且可以独立地扩展和管理测试数据和测试脚本。 +这有助于提高测试的可维护性、可读性和可重用性。 ## 11. 你如何在Selenium中执行JavaScript代码? ```java -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeDriver; - -public class SeleniumJavaScriptExample { - public static void main(String[] args) { +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; + +public class SeleniumJavaScriptExample { + public static void main(String[] args) { // 设置WebDriver的路径(以Chrome为例) - System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); - + System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); + // 创建一个WebDriver实例 - WebDriver driver = new ChromeDriver(); - + WebDriver driver = new ChromeDriver(); + // 导航到网页 - driver.get("https://example.com"); - + driver.get("https://example.com"); + // 将WebDriver实例转换为JavascriptExecutor - JavascriptExecutor jsExecutor = (JavascriptExecutor) driver; - + JavascriptExecutor jsExecutor = (JavascriptExecutor) driver; + // 使用executeScript方法执行JavaScript代码 // 例如,更改页面标题 - jsExecutor.executeScript("document.title = 'New Title';"); - + jsExecutor.executeScript("document.title = 'New Title';"); + // 或者与页面上的元素交互 // 首先,通过常规方式找到元素 - WebElement element = driver.findElement(By.id("someElementId")); - + WebElement element = driver.findElement(By.id("someElementId")); + // 然后,使用JavaScript来操作该元素 // 例如,更改元素的文本内容 - jsExecutor.executeScript("arguments[0].innerText = 'New text';", element); - + jsExecutor.executeScript("arguments[0].innerText = 'New text';", element); + // 关闭浏览器窗口 - driver.quit(); - } + driver.quit(); + } } ``` - ## 13. 在Selenium中,你如何生成测试报告?你使用过哪些测试报告工具? - 在Selenium中,生成测试报告通常涉及以下几个步骤: 1. **编写测试脚本**:首先,你需要使用Selenium WebDriver编写测试脚本,这些脚本会执行一系列的测试用例。 @@ -392,27 +447,38 @@ public class SeleniumJavaScriptExample { - **TestNG**:TestNG是一个基于Java的测试框架,它内置了报告生成功能。当你使用TestNG运行测试时,它会自动生成一个HTML格式的测试报告,其中包含有关测试用例状态、执行时间和错误信息的详细信息。 -- **Allure**:Allure是一个轻量级的多语言测试报告工具,它不仅支持Java,还支持其他许多编程语言。Allure可以生成非常详细和美观的测试报告,包括测试用例的状态、步骤、附件(如截图和日志)等。你可以将Allure与TestNG或JUnit等测试框架结合使用。 +- **Allure** + :Allure是一个轻量级的多语言测试报告工具,它不仅支持Java,还支持其他许多编程语言。Allure可以生成非常详细和美观的测试报告,包括测试用例的状态、步骤、附件(如截图和日志)等。你可以将Allure与TestNG或JUnit等测试框架结合使用。 -- **ExtentReports**:ExtentReports是一个功能强大的测试报告库,专为Java设计。它提供了丰富的自定义选项,允许你创建具有专业外观的测试报告。ExtentReports支持多种格式的报告输出,包括HTML、PDF和CSV等。 +- **ExtentReports** + :ExtentReports是一个功能强大的测试报告库,专为Java设计。它提供了丰富的自定义选项,允许你创建具有专业外观的测试报告。ExtentReports支持多种格式的报告输出,包括HTML、PDF和CSV等。 - **JUnit**:虽然JUnit本身主要是一个单元测试框架,但它也可以与一些插件或工具结合使用来生成测试报告。例如,你可以使用Maven的Surefire插件与JUnit一起运行测试,并使用Maven的Site插件生成测试报告。 -- **CI/CD工具**:在持续集成/持续部署(CI/CD)环境中,你可以使用Jenkins、GitLab CI/CD等工具来自动运行Selenium测试并生成测试报告。这些工具通常提供了插件或集成,以便与上述测试报告工具无缝协作。 +- **CI/CD工具**:在持续集成/持续部署(CI/CD)环境中,你可以使用Jenkins、GitLab + CI/CD等工具来自动运行Selenium测试并生成测试报告。这些工具通常提供了插件或集成,以便与上述测试报告工具无缝协作。 要生成测试报告,你需要在测试脚本中添加适当的监听器或插件来收集测试结果,并在测试执行完成后调用报告生成工具来生成报告。具体实现方式取决于你选择的测试框架和报告工具。 ## 14. 你能描述一下Selenium Grid是如何实现分布式测试的吗? -Selenium Grid允许你在多台机器的多个浏览器上并行地进行测试,即实现分布式测试。Selenium Grid使用Hub和Node模式,一台计算机作为Hub(管理中心)管理其他多个Node(节点)计算机。Hub负责将测试用例分发给多台Node计算机执行,并收集多台Node计算机执行结果的报告,汇总后提交一份总的测试报告。 +Selenium Grid允许你在多台机器的多个浏览器上并行地进行测试,即实现分布式测试。Selenium +Grid使用Hub和Node模式,一台计算机作为Hub(管理中心)管理其他多个Node(节点)计算机。Hub负责将测试用例分发给多台Node计算机执行, +并收集多台Node计算机执行结果的报告,汇总后提交一份总的测试报告。 具体实现过程如下: -1. 启动Selenium Grid,会包含一个Hub。Hub是管理中心,负责管理测试脚本和Node节点。测试人员分别在各自的电脑上到Hub上注册一个或多个Node,每个Node的环境可能不相同(例如操作系统、浏览器版本等),注册的这些信息都会管理在Hub中。 -2. 当在服务器执行测试用例时,Hub会根据测试用例中启动测试的类型来将用例转发给符合匹配要求的Node(即测试代理)。每个Node计算机会执行分发给自己的测试用例,并将执行结果返回给Hub。 +1. 启动Selenium + Grid,会包含一个Hub。Hub是管理中心,负责管理测试脚本和Node节点。 + 测试人员分别在各自的电脑上到Hub上注册一个或多个Node, + 每个Node的环境可能不相同(例如操作系统、浏览器版本等),注册的这些信息都会管理在Hub中。 +2. 当在服务器执行测试用例时,Hub会根据测试用例中启动测试的类型来将用例转发给符合匹配要求的Node(即测试代理)。 + 每个Node计算机会执行分发给自己的测试用例,并将执行结果返回给Hub。 3. Hub收集所有Node计算机的执行结果报告,并进行汇总,最终提交一份总的测试报告。 -通过这种方式,Selenium Grid可以在不同的计算机上分发多个测试用例以并发执行,大大提高了测试用例的执行效率,满足了大型项目自动化测试的时限要求和兼容性要求。同时,由于可以在不同的操作系统和浏览器环境下进行测试,因此也提高了测试的覆盖率和可靠性。 +通过这种方式,Selenium +Grid可以在不同的计算机上分发多个测试用例以并发执行,大大提高了测试用例的执行效率,满足了大型项目自动化测试的时限要求和兼容性要求。 +同时,由于可以在不同的操作系统和浏览器环境下进行测试,因此也提高了测试的覆盖率和可靠性。 ## 15. 在你的自动化测试经验中,你如何保证测试的稳定性和可靠性? diff --git "a/docs/test/\345\216\213\345\212\233\346\265\213\350\257\225.md" "b/docs/test/\345\216\213\345\212\233\346\265\213\350\257\225.md" index fa5012a..1b6f95f 100644 --- "a/docs/test/\345\216\213\345\212\233\346\265\213\350\257\225.md" +++ "b/docs/test/\345\216\213\345\212\233\346\265\213\350\257\225.md" @@ -48,20 +48,22 @@ Affect(class count: 2 , method count: 2) cost in 374 ms, listenerId: 7 `---[0.03% 0.007384ms ] com.test.common.to.PaginationResponse:setTotal() #148 ``` -1. java一般的ger/set方法,比如**getPageSize**,消耗的是0.008099ms,就是8.099ns,非常短 +1. java语句中,一般的ger/set方法,比如**getPageSize**,消耗的是0.008099ms,就是8.099ns,非常短 2. java的(小规模)集合操作,会耗时一小会,[0.37% 0.096225ms ] java.util.List:sort() #145 3. IO消耗的时间长[79.70% 20.763484ms ] com.test.repository.mapper.voucher.TestMapper:selectPage() #137 -综合上面的测试及描述。一些核心接口在压力测试时,就要评估好QPS以及TPS。评估时要全面考虑接口的 -复杂度,后续调用链路的长短。一般情况下。电商各条业务线的TPS和QPS可以粗略评估如下 +综合上面的测试及描述。一些核心接口在压力测试时, +就要评估好QPS以及TPS。评估时要全面考虑接口的 +复杂度,后续调用链路的长短。 +一般情况下。电商各条业务线的TPS和QPS可以粗略评估如下 # 2. 支付 一般支付有读写操作都频繁的核心接口如下 -- 核心支付 单机TPS一般在500左右 +- 核心支付 单机TPS一般在500左右 - 取消订单 单机TPS一般在1000左右 -- 订单查询 +- 订单查询 # 3. 交易 diff --git "a/docs/test/\345\276\256\344\277\241\346\224\257\344\273\230\344\270\232\345\212\241.md" "b/docs/test/\345\276\256\344\277\241\346\224\257\344\273\230\344\270\232\345\212\241.md" index a26f8e9..6287bc8 100644 --- "a/docs/test/\345\276\256\344\277\241\346\224\257\344\273\230\344\270\232\345\212\241.md" +++ "b/docs/test/\345\276\256\344\277\241\346\224\257\344\273\230\344\270\232\345\212\241.md" @@ -12,19 +12,18 @@ parent: Test ### 1.1.1. 签约 -#### 1.1.1.1. 特约商户进件 +**特约商户进件** - https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter11_1_1.shtml - + 比如具体一家电商公司,审核通过以后,会返回一个唯一的sub_mchid -#### 1.1.1.2. 二级商户进件 +**二级商户进件** - https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_1_1.shtml 比如某家电商公司的供应商 - ```text 非小微的主体类型需与营业执照/登记证书上一致,可参考选择主体指引,枚举值如下。 2401:小微商户,指无营业执照的个人商家。 @@ -41,7 +40,6 @@ parent: Test - https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_3_3.shtml - 主单中关键信息:商户号、支付者信息、主订单 - - 子单中关键信息:商户号、二级商户号 ### 1.1.3. 分账 @@ -52,10 +50,9 @@ parent: Test - 微信订单号 - 商户分账单号:body 商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。 - 分账接收方列表 - - 分账接收方账号 - - 分账金额 - - 分账接收方类型 - + - 分账接收方账号 + - 分账金额 + - 分账接收方类型 ```mermaid mindmap @@ -71,6 +68,7 @@ mindmap 供应商 ``` + - 供应商结算价=销售价-门提-平台服务费 - (平台服务费+门提+保证金)/销售价<=90% - (平台服务费+门提+广告营销费)/销售价<=90% @@ -85,11 +83,11 @@ mindmap ### 1.2.1. 退款 - https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_1.shtml -当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家账户上。 - +当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家, +微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家账户上。 ### 1.2.2. 取消补差 -- https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_5_3.shtml +- https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_5_3.shtml - 对带有补差标识的订单,如果不需要补差,可在发起分账前,可调用这个接口进行取消补差。 \ No newline at end of file diff --git "a/docs/test/\346\265\213\350\257\225\345\271\263\345\217\260\345\217\212\345\267\245\345\205\267.md" "b/docs/test/\346\265\213\350\257\225\345\271\263\345\217\260\345\217\212\345\267\245\345\205\267.md" index adf5f3a..fa4825e 100644 --- "a/docs/test/\346\265\213\350\257\225\345\271\263\345\217\260\345\217\212\345\267\245\345\205\267.md" +++ "b/docs/test/\346\265\213\350\257\225\345\271\263\345\217\260\345\217\212\345\267\245\345\205\267.md" @@ -6,7 +6,9 @@ parent: Test # 1. 移动端测试 -移动端测试是指针对移动设备(如智能手机、平板电脑等)上的应用程序进行的一系列质量保证活动,以确保应用的功能、性能、兼容性以及用户体验达到预期标准。以下是移动端测试的主要内容和步骤: +移动端测试是指针对移动设备(如智能手机、平板电脑等)上的应用程序进行的一系列质量保证活动, +以确保应用的功能、性能、兼容性以及用户体验达到预期标准。 +以下是移动端测试的主要内容和步骤: 1. **安装/卸载测试**: - 安装测试包括验证应用程序能否正确从应用商店或其他渠道下载并成功安装在不同类型的设备上。 @@ -43,23 +45,26 @@ parent: Test 9. **用户体验测试**: - 用户友好性、易用性、可访问性的评估,考虑无障碍功能是否完善,符合人机交互设计原则。 -综合以上测试类型,一个全面的移动端测试策略需要覆盖各种真实用户场景,确保最终发布的应用程序能够在多种条件和环境下为用户提供优质体验。 +综合以上测试类型,一个全面的移动端测试策略需要覆盖各种真实用户场景, +确保最终发布的应用程序能够在多种条件和环境下为用户提供优质体验。 # 2. 常用测试工具 - Jacoco:代码覆盖率 - ExtentReport:java测试报告 - - jmeter: Apache JMeter是一款开源的性能测试工具,是使用率最高的性能测试工具之一,能够对Web应用进行测试。 -JMeter最初被设计用于进行Web应用测试,但后来扩展到了其他测试领域,可用于测试静态和动态资源,如静态文件、Java小服务程序、CGI脚本、Java对象、数据库和FTP服务器等等。 +JMeter最初被设计用于进行Web应用测试,但后来扩展到了其他测试领域,可用于测试静态和动态资源, +如静态文件、Java小服务程序、CGI脚本、Java对象、数据库和FTP服务器等等。 使用JMeter,可以对服务器、网络或对象模拟巨大的负载,在不同压力类别下测试它们的强度和分析整体性能。 -另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证程序是否返回了期望结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。 +另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证程序是否返回了期望结果。 +为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。 JMeter的体系结构包括一个线程池,在线程池中模拟用户的并发行为。采样器可以理解为用户发起的请求, -比如发起获取用户列表的一起请求,在发起请求之前,可能需要登录验证,这时候可以在前置处理器中将身份牌亮出来,以便服务器能够接受发起的请求。 +比如发起获取用户列表的一起请求,在发起请求之前,可能需要登录验证, +这时候可以在前置处理器中将身份牌亮出来,以便服务器能够接受发起的请求。 总的来说,JMeter是一个功能强大的开源工具,可用于对Web应用进行压力测试和性能分析。 @@ -68,30 +73,46 @@ JMeter的体系结构包括一个线程池,在线程池中模拟用户的并 Selenium是一个用于Web应用程序测试的工具,可以直接在浏览器中运行测试,就像真正的用户在操作一样。 它支持多种浏览器,包括IE、Firefox、Safari、Chrome、Opera和Edge等。 Selenium的主要功能包括测试与浏览器的兼容性,测试系统功能,支持自动录制动作和自动生成不同语言的测试脚本。 -Selenium可以用于自动化测试和爬虫模拟人操作浏览器,是目前最广泛使用的开源Web UI(用户界面)自动化测试套件之一。 +Selenium可以用于自动化测试和爬虫模拟人操作浏览器, +是目前最广泛使用的开源Web UI(用户界面)自动化测试套件之一。 - appnium -Appium是一个开源、跨平台(测试程序跨平台、支持多平台上的app测试)、多语言支持的移动应用自动化工具。它主要用于对iOS、Android和Windows上的原生、移动Web和混合应用进行自动化测试。 +Appium是一个开源、跨平台(测试程序跨平台、支持多平台上的app测试)、多语言支持的移动应用自动化工具。 +它主要用于对iOS、Android和Windows上的原生、移动Web和混合应用进行自动化测试。 Appium可以测试原生应用,这些应用是用iOS、Android或者Windows -SDK编写的。它也可以测试移动Web应用,这些应用是通过移动端浏览器访问的。另外,Appium还可以测试混合应用,这些应用带有“webview”包装器,用来和Web内容交互的原生控件。 +SDK编写的。它也可以测试移动Web应用,这些应用是通过移动端浏览器访问的。 +另外,Appium还可以测试混合应用,这些应用带有“webview”包装器,用来和Web内容交互的原生控件。 -Appium的另一个重要特性是跨平台。它允许使用同样的API对多个平台(iOS、Android、Windows)进行测试,并能够在iOS、Android和Windows测试套件之间复用代码。 +Appium的另一个重要特性是跨平台。 +它允许使用同样的API对多个平台(iOS、Android、Windows)进行测试, +并能够在iOS、Android和Windows测试套件之间复用代码。 -此外,Appium支持多种开发语言,如Python、Java、Ruby、JavaScript、PHP和C#等,这意味着开发者可以使用他们熟悉的编程语言来编写测试程序。 +此外,Appium支持多种开发语言,如Python、Java、Ruby、JavaScript、PHP和C#等, +这意味着开发者可以使用他们熟悉的编程语言来编写测试程序。 - airtest -Airtest是一个跨平台的UI自动化测试框架,适用于游戏和应用程序。它基于图像识别原理,使用图像识别技术来定位UI元素,无需嵌入任何代码对游戏和应用进行自动化测试。Airtest支持Windows、Android平台和iOS平台,提供跨平台的API,包括安装应用、模拟输入、断言等。Airtest还提供了一个强大的GUI工具AirtestIDE,可以录制和调试测试脚本,给QA人员提供了完整的工作流程支持。 +Airtest是一个跨平台的UI自动化测试框架,适用于游戏和应用程序。它基于图像识别原理, +使用图像识别技术来定位UI元素,无需嵌入任何代码对游戏和应用进行自动化测试。 +Airtest支持Windows、Android平台和iOS平台,提供跨平台的API,包括安装应用、模拟输入、断言等。 +Airtest还提供了一个强大的GUI工具AirtestIDE,可以录制和调试测试脚本, +给QA人员提供了完整的工作流程支持。 -使用Airtest可以节省人力、物力、时间、硬件资源等,提升测试效率,特别对于繁琐重复的测试用例,可以使测试人员更专注于新的测试模块的建立和开发,从而提高测试覆盖率。 +使用Airtest可以节省人力、物力、时间、硬件资源等,提升测试效率,特别对于繁琐重复的测试用例, +可以使测试人员更专注于新的测试模块的建立和开发,从而提高测试覆盖率。 - monkey: -Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。这种测试方法是一种快速有效的测试方法,旨在测试软件的稳定性、健壮性。 +Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。 +它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等), +实现对正在开发的应用程序进行压力测试。 +这种测试方法是一种快速有效的测试方法,旨在测试软件的稳定性、健壮性。 -Monkey程序是Android系统自带的,由Java语言写成,在Android文件系统中的存放路径是:/system/framework/monkey.jar。要运行Monkey程序需要通过adb(Android +Monkey程序是Android系统自带的,由Java语言写成, +在Android文件系统中的存放路径是:/system/framework/monkey.jar。 +要运行Monkey程序需要通过adb(Android Debug Bridge)来运行。 # 3. 代码扫描 diff --git "a/docs/test/\346\267\230\345\256\235\345\211\215\345\217\260\347\263\273\347\273\237\346\200\247\350\203\275\345\210\206\346\236\220\344\272\216\344\274\230\345\214\226.md" "b/docs/test/\346\267\230\345\256\235\345\211\215\345\217\260\347\263\273\347\273\237\346\200\247\350\203\275\345\210\206\346\236\220\344\272\216\344\274\230\345\214\226.md" index 87f8c22..dc6865e 100644 --- "a/docs/test/\346\267\230\345\256\235\345\211\215\345\217\260\347\263\273\347\273\237\346\200\247\350\203\275\345\210\206\346\236\220\344\272\216\344\274\230\345\214\226.md" +++ "b/docs/test/\346\267\230\345\256\235\345\211\215\345\217\260\347\263\273\347\273\237\346\200\247\350\203\275\345\210\206\346\236\220\344\272\216\344\274\230\345\214\226.md" @@ -48,6 +48,10 @@ parent: Test ## 3.1. cpu +- 正则表达式匹配 + +过长的正则表达式匹配,会消耗极大的内存 + - 字符拼接、查找、替换 合理使用StringBuilder,不使用StringBuffer。