赞
踩
补一下之前的面经,应该是上个月月底面的,纯纯的kpi,算是社招种体验最差的一次面试了。
业务部应该是无人机,还是无人车我有些记不清了,应该是无人机。
因为是被捞的,所以开始先问对测开了解吗,对测试的东西了解知道不,然后正式开始。
面试官是个大姐,头发凌乱,眼睛睁不开,一脸苦瓜脸加不屑的感觉。
项目相关,具体的一些深挖问题
MySQL四种隔离级别
MySQL提供了四种隔离级别,分别是:
READ UNCOMMITTED(未提交读):这是最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据。这可能导致脏读(读取到未提交的数据)和不可重复读(读取到同一数据但值不同)。在MySQL中,该级别不常用。
READ COMMITTED(提交读):这是MySQL的默认隔离级别。它允许一个事务读取另一个事务已经提交的数据。这可以避免脏读,但是可能导致不可重复读(读取到同一数据但值不同)和幻读(读取到另一个事务插入的新数据)。
REPEATABLE READ(可重复读):这个隔离级别保证在同一事务内多次读取同一数据时,结果始终相同。它避免了脏读和不可重复读,但可能导致幻读(读取到另一个事务插入的新数据)。在MySQL中,该级别是最常用的。
SERIALIZABLE(可串行化):这是最高的隔离级别,它通过强制事务串行执行来避免脏读、不可重复读和幻读。这意味着只有一个事务可以访问数据,而其他事务必须等待。这种级别可以保证数据的完整性,但是对性能影响较大,在MySQL中也不常用。
MVCC说一下
MVCC,即多版本并发控制,是一种用于实现数据库并发控制的技术,它主要用于解决数据库并发操作时可能出现的一些问题,如丢失修改、不可重复读、幻读等。
在 MVCC 中,每次对数据库进行修改操作时,会生成一个新的版本,而不是直接覆盖原有的数据。每个事务在读取数据时,只会看到早于该事务开始时间的版本数据,而不会看到后续的修改。这样,可以实现并发事务之间的隔离,从而保证每个事务执行时都能够看到一致的数据。
MVCC 的实现方法是在每行记录上增加一个版本号或时间戳,以及一个删除标记,来标记该记录是否被删除。当一个事务开始时,会创建一个快照(snapshot),记录当前数据库中的所有数据版本和删除标记。在事务执行过程中,如果其他事务修改或删除了某些数据,该数据会被标记为“已删除”,但不会直接删除该行记录。这样,当前事务就能读取到该行记录的旧版本。
MVCC 可以提高数据库的并发性能,因为多个事务可以同时读取数据库中的数据,而不会互相阻塞。但是,在使用 MVCC 时也需要注意,如果事务太多,会导致数据库中存在大量的版本数据,从而增加了数据库的存储空间和查询时间。因此,需要根据实际情况选择适当的隔离级别和并发控制方式。
用没用过分库分表,啥情况用的
通常情况下,当应用的数据量达到一定规模时,为了应对高并发和大数据量的数据访问,会使用分库分表技术。
分库分表是将一个大的数据库分成多个小的数据库(分库),每个小的数据库再将数据表分成多个小的数据表(分表),从而实现数据的分散存储和查询。
使用分库分表的主要情况包括:
数据库性能瓶颈:当单个数据库的负载达到瓶颈时,为了提高数据库的并发处理能力,可以将数据划分到多个数据库中。
数据库容量限制:当单个数据库无法存储所有数据时,可以将数据划分到多个数据库中,以增加存储容量。
数据访问热点:当某个数据表的数据访问量很大时,为了减轻该数据表的负载,可以将该表数据分散到多个数据表中,从而提高查询性能。
业务需求:当业务需求需要多个数据库共同完成时,例如多个地区的用户数据需要分别存储在不同的数据库中,可以使用分库分表来实现。
需要注意的是,分库分表虽然可以提高数据库的性能和扩展性,但也带来了一些挑战,例如分布式事务、数据一致性、数据迁移、备份和恢复等问题。因此,在使用分库分表时需要仔细考虑其对系统的影响,并选择合适的分片策略和工具来实现。
MySQL优化
MySQL 优化包括以下几个方面:
硬件配置优化:包括 CPU、内存、磁盘等硬件资源的配置和优化,例如增加 CPU 核心、扩容内存、使用固态硬盘等。
数据库配置优化:包括 MySQL 的配置参数优化,例如缓存大小、并发连接数、线程池大小等。
索引优化:索引是优化数据库性能的重要手段,可以使用适当的索引提高查询速度和减少查询的磁盘 I/O 次数。
SQL 语句优化:SQL 语句是操作数据库的重要手段,可以通过优化 SQL 语句的结构和语法,减少查询数据量和优化查询逻辑,提高查询性能。
分区表优化:分区表是 MySQL 支持的一种特殊表结构,可以将一个大表拆分成多个小表,从而提高数据查询和更新的性能。
数据库架构优化:数据库架构设计和优化也是提高数据库性能的重要手段,可以通过优化数据库的设计和调整数据模型来提高查询性能和减少数据冗余。
需要注意的是,不同的优化手段针对的问题和适用场景不同,需要结合具体的业务需求和数据库性能瓶颈来选择和采用。同时,优化也不是一次性完成的,需要不断地观察和调整,以适应不断变化的业务需求和数据规模。
Redis缓存穿透
Redis缓存穿透是指缓存中没有需要查询的数据,导致请求全部发送到数据库,从而导致数据库的压力增大。
缓存穿透通常发生在以下情况:
查询一个不存在的数据,比如查询一条ID为负数的数据。
恶意攻击或非法访问,比如利用爆破算法试图查询所有可能的ID,以此来耗尽系统的资源。
为了避免缓存穿透,可以使用以下几种方法:
布隆过滤器:布隆过滤器是一种空间效率很高的随机数据结构,可以用于判断一个元素是否在集合中存在。可以将可能的查询键事先存储在布隆过滤器中,当查询请求到来时,先判断该键是否在布隆过滤器中,如果不在则直接返回空结果,否则再查询缓存或数据库。
缓存空值:可以将不存在的键值对存储到缓存中,缓存时间较短,一段时间后自动失效。这样下一次查询同样不存在的键时,会从缓存中获取到这个空值,避免直接查询数据库。
数据预热:在系统启动时,将常用的数据加载到缓存中,以减少第一次查询时的数据库压力。
限制访问频率:限制访问频率可以有效地防止恶意攻击和非法访问。
需要注意的是,以上方法仅仅是避免缓存穿透的一些常用手段,但并不是绝对的解决方案。在实际应用中,需要根据具体情况选择合适的方法来保障系统的安全和稳定性。
缓存雪崩
缓存雪崩是指在缓存中存储的大量数据在同一时间段内过期失效,导致大量请求直接落到后端数据库,从而引起数据库的性能问题。
缓存雪崩通常发生在以下情况:
缓存服务器宕机或重启。
缓存数据过期时间设置不合理,导致大量缓存数据在同一时间内过期失效。
缓存中存储的数据集中在某个热点键上,当这个热点键过期时,大量请求直接落到后端数据库。
为了避免缓存雪崩,可以使用以下几种方法:
设置过期时间的随机值:可以在缓存数据的过期时间上增加一个随机值,以使缓存数据的过期时间分散开来,避免大量数据在同一时间点过期。
搭建集群:将缓存服务器搭建成集群,通过多台缓存服务器分担请求,降低单点故障的风险。
热点数据永不过期:将热点数据的过期时间设置为永不过期,可以保证热点数据始终有效,避免因热点数据过期而引发的缓存雪崩问题。
限流降级:对于超出系统承受范围的请求,可以通过限流或降级的方式来保护系统的稳定性。
需要注意的是,以上方法仅仅是避免缓存雪崩的一些常用手段,但并不是绝对的解决方案。在实际应用中,需要根据具体情况选择合适的方法来保障系统的安全和稳定性。
redis 持久化机制
Redis 提供了两种持久化机制,分别是 RDB 和 AOF。
RDB 是 Redis 的一种快照持久化方式,可以将 Redis 在某个时间点上的数据保存到一个文件中。RDB 持久化的优点是对 Redis 的影响较小,因为是将 Redis 内存中的数据写入到磁盘中,所以不会对 Redis 的性能产生太大的影响。同时,RDB 文件也很紧凑,因为它只包含了 Redis 数据库中在某个时间点上的数据。
RDB 持久化方式有两种触发方式:手动和自动。手动触发可以使用 SAVE
命令,将 Redis 数据库强制写入到硬盘中。而自动触发则可以通过 save
或者 bgsave
配置来实现。前者是指当满足一定条件(例如当前 Redis 数据库中键的数量超过了指定的数量,或者键被修改的次数超过了指定的次数)时,Redis 就会执行 RDB 持久化;后者是指 Redis 在后台异步执行 RDB 持久化,这样就不会阻塞 Redis 的主线程。
AOF 是 Redis 的另一种持久化方式,全称为 Append Only File,即追加式文件。与 RDB 不同,AOF 持久化方式是将 Redis 的操作日志保存到一个文件中。这个文件可以通过 replay 操作来恢复 Redis 数据库的状态。AOF 持久化方式有以下优点:
操作日志更加详细,可以减少数据丢失的可能性。
可以保证 Redis 数据库在意外宕机时,尽可能地不会出现数据损坏的情况。
相对于 RDB,AOF 更加耗费资源,因为它需要将所有的 Redis 操作都写入到磁盘中。同时,AOF 文件也比较大,因为它包含了 Redis 数据库所有的操作记录。
与 RDB 类似,AOF 也支持两种触发方式:手动和自动。手动触发可以使用 BGREWRITEAOF
命令,强制 Redis 对 AOF 文件进行重写;而自动触发则可以通过 auto-aof-rewrite-percentage
和 auto-aof-rewrite-min-size
配置来实现。前者是指当 AOF 文件大小超过当前文件大小的一定百分比(默认为 100%),Redis 就会执行 AOF 重写;后者是指当 AOF 文件大小超过指定大小时,Redis 就会执行 AOF 重写。
哨兵工作机制
哨兵(Sentinel)是Redis提供的高可用性解决方案之一,其作为一个独立的进程来运行,用于监控Redis主节点的健康状况,并在主节点宕机时自动将其中的一个从节点升级为主节点,以保证系统的可用性。
哨兵的工作机制如下:
哨兵定期向主节点发送PING命令,以检测主节点的健康状况。
如果哨兵连续多次没有收到主节点的PONG响应,即认为主节点已经宕机。
在主节点宕机后,哨兵会从所有的从节点中选出一个作为新的主节点,并将其升级为主节点。
哨兵会向所有客户端发布一条通知,告知新的主节点地址和端口号。
哨兵会向新的主节点发送配置命令,让其将所有从节点配置为自己的从节点,并更新所有从节点的主节点地址和端口号。
当原来的主节点重新启动后,它会变成新的从节点,并根据新的主节点进行同步复制数据。
需要注意的是,哨兵本身也可能出现故障,因此在实际应用中,需要将哨兵部署在不同的服务器上,以提高系统的可用性。此外,哨兵还支持多个哨兵之间的相互监控,以提高系统的容错能力。
JVM内存分区
JVM 内存分为以下几个区域:
程序计数器是一块较小的内存区域,它可以看作是当前线程所执行的字节码行号指示器。在虚拟机中,每个线程都有自己独立的程序计数器,以保证线程切换后能恢复到正确的执行位置。程序计数器是线程私有的,因此不会产生线程安全问题。
Java 虚拟机栈也称为 Java 方法栈,用于存储每个方法在执行时的局部变量表、操作数栈、动态链接、方法出口等信息。与程序计数器相似,虚拟机栈也是线程私有的,每个线程都有自己独立的虚拟机栈。
本地方法栈和虚拟机栈类似,不同之处在于本地方法栈用于存储 JNI 方法(即使用 C 语言或其他本地语言实现的方法)的信息。虚拟机规范并没有规定本地方法栈的具体实现方式,但通常来说,它与虚拟机栈是相似的。
Java 堆是 Java 虚拟机中最大的一块内存区域,用于存储对象实例和数组。Java 堆是所有线程共享的,因此会产生线程安全问题。
方法区也称为永久代,用于存储类的信息、常量池、静态变量、即时编译器编译后的代码等数据。在 JDK8 及之后的版本中,方法区被移除,取而代之的是元空间(Metaspace)。
运行时常量池用于存储编译期生成的各种字面量和符号引用,它是方法区的一部分。与 Java 堆类似,运行时常量池也是线程共享的。
垃圾回收机制
Java垃圾回收机制是Java语言的一个重要特性之一,它通过自动化管理内存来提高程序的可靠性和可维护性。Java垃圾回收机制主要包括以下几个方面:
对象的创建:Java程序在运行时会不断地创建新的对象,这些对象被分配在Java虚拟机的堆内存中。
引用计数:Java虚拟机采用引用计数的方式来跟踪对象的引用情况,当一个对象被引用时,其引用计数加一,当一个对象不再被引用时,其引用计数减一。
垃圾收集器:Java虚拟机内置了多种垃圾收集器,用于定期回收不再被引用的对象,释放被占用的内存。
标记清除算法:Java虚拟机采用标记清除算法来回收垃圾,该算法将堆内存分为两个区域,一个用于存放活动对象,一个用于存放垃圾对象,当垃圾收集器启动时,会先标记所有活动对象,然后清除所有未被标记的对象。
分代收集算法:Java虚拟机还采用分代收集算法,将堆内存分为新生代和老年代两个部分,新生代用于存放新创建的对象,老年代用于存放长时间存活的对象,不同的垃圾收集器会根据对象的年龄将其分配到不同的代中,以提高垃圾回收的效率。
垃圾回收的触发:Java虚拟机会根据堆内存的使用情况来触发垃圾回收,当堆内存占用超过某个阈值时,就会启动垃圾回收器,回收不再被引用的对象。
需要注意的是,垃圾回收机制虽然方便了Java程序员的开发工作,但过多的垃圾回收会对程序的性能产生一定的影响,因此在实际应用中,需要根据程序的特点和实际情况,合理地调整垃圾回收的策略和参数,以提高程序的性能和响应速度。
OOM
OOM 是 OutOfMemoryError 的缩写,意为内存不足错误。当 Java 虚拟机无法再分配内存时,就会抛出 OOM 错误。这种情况通常是由以下原因所引起的:
内存泄漏(Memory Leak):程序中有大量的对象没有及时释放,导致内存占用过高。
内存溢出(Memory Overflow):程序使用了过多的内存空间,超出了 JVM 所设置的最大内存限制。
过度创建大对象:在应用程序中,频繁地创建大型对象,导致内存速度耗尽。
并发线程数过多:应用程序中开启了过多的线程,导致 JVM 内部线程栈占用过多内存。
当出现 OOM 错误时,我们可以通过以下步骤来解决问题:
寻找内存泄漏点:使用内存分析工具,查看程序中哪些对象没有得到释放,进行相应的调整。
加大 JVM 内存限制:如果应用程序中确实需要大量内存空间,可以通过修改 JVM 启动参数,来增加 JVM 的内存限制。
优化程序:尽可能避免频繁地创建大型对象,在编写代码时,注意内存使用情况。并发线程数也要适当控制。
优化代码:使用集合类时注意及时删除无用元素,尽可能避免使用静态变量等,减小内存开销。
总之,在应用程序开发中,避免 OOM 错误的发生,需要我们具备一些基本的内存管理知识,并且针对不同情况采取相应的解决方案。
双亲委派,有哪些打破双亲委派机制的例子吗
在Java语言中,双亲委派机制是一种类加载机制,它要求除了顶层的启动类加载器外,每个类加载器都有一个父类加载器,当一个类加载器需要加载一个类时,它首先将这个任务委派给它的父类加载器来完成。如果父类加载器无法完成此任务(即在它的搜索范围内找不到对应的类),该类加载器才会尝试自己加载这个类。这种机制可以避免类的重复加载,保证Java核心库的安全性和稳定性。
但是也有一些特殊情况下需要打破双亲委派机制,例如OSGi框架、Web应用程序等场景。在OSGi框架中,每个组件(Bundle)都有自己的类加载器,它们之间的类加载是相互独立的,需要打破双亲委派机制;在Web应用程序中,不同Web应用程序之间需要共享同一个类,但是它们各自的类加载器是不同的,这也需要对双亲委派机制进行打破。
因此,在这些特殊情况下,需要通过编写自定义类加载器或者使用特殊的类加载器来打破双亲委派机制,以满足特定的需求。
三次握手说一下
TCP 是面向连接的协议,使用三次握手建立连接,四次挥手断开连接。以下是三次握手过程:
客户端向服务端发送 SYN 报文段,其中 SYN 标志位被置为 1,表示客户端请求建立连接。
服务端接收到 SYN 报文段后,如果同意建立连接,则向客户端发送 SYN-ACK 报文段,其中 SYN 和 ACK 标志位都被置为 1,表示服务端同意建立连接,并且通知客户端下一步需要发送数据给服务端。
客户端接收到服务端的 SYN-ACK 报文段后,向服务端发送一个 ACK 报文段,其中 ACK 标志位被置为 1,表示客户端确认连接已经建立。此时,客户端和服务端之间的连接就建立成功了,可以进行数据传输了。
三次握手的目的是确保客户端和服务端之间能够相互通信,避免无效连接的产生。具体来说,第一次握手是客户端向服务端发出请求,第二次握手是服务端响应客户端请求并同意建立连接,第三次握手是客户端确认服务端的响应,同时也通知服务端客户端已经准备好发送数据。这样,就能够确保客户端和服务端之间有一个可靠的连接,可以进行正常的数据传输。
TCP和UDP
TCP和UDP是两种互联网传输协议。TCP(Transmission Control Protocol)是一种面向连接的、可靠性高的协议,它通过三次握手的方式建立连接、进行数据传输并断开连接。而UDP(User Datagram Protocol)则是一种无连接、简单的协议,它不保证数据传输的可靠性,但传输速度快。
TCP在互联网上应用广泛,例如网页浏览、邮件发送等应用程序都使用TCP协议。因为TCP能够保证数据的可靠传输,确保数据不会丢失、损坏或重复,可以满足这些应用程序对数据传输的要求。另外,TCP还有拥塞控制的机制,可以避免过多的数据包堆积导致网络拥堵。
UDP则适用于实时性要求高的应用程序,例如在线游戏、流媒体传输等。由于UDP不保证数据的可靠传输,所以在传输过程中可能会出现数据包丢失、乱序等问题,但是它传输速度快,可以满足对实时性要求高的应用程序的需求。
为什么TCP可靠传输
TCP协议之所以能够保证可靠传输,主要是因为它具有以下几个机制:
建立连接:在进行数据传输之前,TCP需要先进行“三次握手”建立连接,确认两端的通信正常,确保双方都可以接收和发送数据。
确认应答:TCP在发送数据时,会等待接收方的确认应答,以确保数据已经正确到达。如果没有收到确认应答,TCP会尝试重传该数据。
滑动窗口:TCP使用滑动窗口的方式对数据进行流量控制。发送方和接收方需要动态地协调发送数据的速率,以避免网络拥塞和丢包现象。发送方通过滑动窗口的调整来控制发送数据的速率,接收方则通过确认应答来控制接收数据的速率。
超时重传:在网络传输中,有可能会出现数据包丢失或损坏的情况。为了确保数据的可靠传输,TCP会设置超时定时器,如果在规定时间内没有收到确认应答,就会进行数据的重传。
拥塞控制:当网络拥堵时,TCP会通过慢启动、拥塞避免和快速恢复等机制来进行拥塞控制,以确保网络的可靠性和稳定性。
综上所述,TCP之所以能够实现可靠传输,是因为它具有建立连接、确认应答、滑动窗口、超时重传和拥塞控制等多种机制,能够有效地避免数据丢失、损坏或重复,确保数据的正确传输。
TCP报文段能介绍下吗
TCP 报文段是 TCP 协议中的数据传输单元,在传输层进行控制和传递。一个 TCP 报文段由报头和数据两部分组成,具体结构如下:
报头(Header):占用 20 字节,包含了一些控制信息,例如源端口、目标端口、序列号、确认号、标志位等。
数据(Data):根据需要可以包含零或多个字节的数据内容,最长为 65,535 字节。
TCP 报文段的主要功能有:
确认收到的数据:通过确认号字段,告诉对端已经接收到哪些数据。
分段与重组:当数据量过大时,TCP 将其分成若干个报文段进行传输,并在接收端重新组装。
流量控制:通过窗口字段,告知对端自己还能接收多少数据,以控制发送端的数据量。
拥塞控制:通过拥塞窗口字段,调整自身的发送速率,避免网络拥塞。
数据保证可靠性:通过重传机制、超时重传机制、累计确认机制等方式,确保数据的可靠传输。
TCP 报文段相较于 UDP 报文没有长度限制,但是报文的头部较长,因此会占用更多的网络资源。同时,TCP 报文段具有可靠性、流量控制和拥塞控制等优势,更加适合需要可靠传输和控制网络负载的应用场景。
多线程有几种方式实现,优缺点说一下
多线程有以下几种方式实现:
继承 Thread 类:通过继承 Thread 类,并重写 run() 方法,来创建新的线程。这种方式简单易用,但是由于 Java 不支持多重继承,所以子类不能再继承其他类。
实现 Runnable 接口:通过实现 Runnable 接口,并将其作为参数传递给 Thread 类的构造方法,来创建新的线程。这种方式比较灵活,可以避免由于类继承而产生的单继承限制。
实现 Callable 接口:与实现 Runnable 接口类似,不同之处在于 Callable 接口支持返回值和抛出异常,且必须使用 FutureTask 类来获取返回值。
创建线程池:通过线程池管理线程,避免频繁地创建和销毁线程。线程池可以控制线程的数量,避免无效的线程开销。
使用 Fork/Join 框架:Java 7 中引入了 Fork/Join 框架,用于分治任务并发处理,将大任务拆分成若干个小任务,每个小任务分配一个线程执行,并将结果汇总。
以上这些方式都可以用于实现多线程,具体选择哪种方式取决于应用场景和需求。继承 Thread 类和实现 Runnable 接口都比较简单,适合于一些比较简单的并发任务;使用 Callable 接口可以获取到线程执行结果和异常信息,更加灵活;线程池管理线程可以避免频繁地创建和销毁线程,提高程序的效率;Fork/Join 框架则适用于大规模的并行计算和分治任务
线程池实现过吗,用来做了什么,用到哪些参数,说下线程池常用阻塞队列
了解线程池的实现。线程池是一种用于并发执行任务的技术,它通过管理和重用线程来提高性能和可伸缩性。
在线程池中,需要指定以下参数:
corePoolSize:线程池的核心线程数量,即保持运行的线程数。
maximumPoolSize:线程池的最大线程数量,即允许创建的最多线程数。
keepAliveTime:当线程池中线程数量超过核心线程数量时,多余的空闲线程的存活时间。
TimeUnit:keepAliveTime 的时间单位。
workQueue:存储还未被执行的任务的阻塞队列。
threadFactory:用于创建新线程的工厂方法。
RejectedExecutionHandler:当线程池无法继续添加任务时,处理被拒绝的任务的策略。
线程池常用的阻塞队列包括:
ArrayBlockingQueue 这是一个基于数组实现的阻塞队列,在构造时需要指定队列大小。当队列已满时,新的任务将被阻塞,等待其他任务被取走后再进行执行。
LinkedBlockingQueue 这是一个基于链表实现的阻塞队列,可以指定队列大小,但如果不指定大小,则默认为 Integer.MAX_VALUE。当队列已满时,新的任务将被阻塞,等待其他任务被取走后再进行执行。
SynchronousQueue 这是一个没有容量的阻塞队列,每个插入操作都要等待一个相应的删除操作,反之亦然。因此,它通常用于将生产者和消费者配对的情况。
以上是我了解的线程池实现以及常用的阻塞队列。
ThreadLocal说一下
ThreadLocal
是一种 Java 中的线程封闭机制,它是一个用于创建线程本地变量的类。在使用 ThreadLocal
的情况下,每个线程都会有自己独立的变量拷贝,因此不同线程之间的数据不会互相干扰。
使用 ThreadLocal
时,我们可以调用 set()
方法为当前线程设置一个值,然后在需要访问这个值的时候,调用 get()
方法获取它。由于每个线程都有自己独立的变量,因此每个线程设置的值不会被其他线程看到,也就避免了线程安全问题。
测试用例设计往一个微信群里发文件
包括但不限于以下用例:
基于“往一个微信群里发文件”这个场景,以下是一些测试用例的设计:
测试文件上传功能。步骤:
确认能够选择要上传的文件。
点击发送按钮后,文件是否能被成功上传到微信服务器。
验证文件上传后是否能在聊天记录中正确显示。
测试不同类型的文件上传。步骤:
尝试上传各种类型的文件,如文本文件、图片、视频、音频等。
具体验证方法与步骤1相同。
测试大文件上传。步骤:
选择一个大型文件进行上传操作。
确认文件是否可以被成功上传,并且速度是否在合理范围内。
验证文件上传后是否能在聊天记录中正常显示。
测试多个文件同时上传。步骤:
选择多个文件进行上传操作。
确认文件是否可以被成功上传,并且速度是否符合预期。
验证所有文件上传完成后,它们是否都能够在聊天记录中正常显示。
测试文件下载功能。步骤:
选择一个已经上传到聊天记录中的文件。
点击下载按钮,确认文件能够被成功下载到本地。
验证下载文件的内容是否与上传时的一致。
测试上传文件失败的情况。步骤:
尝试上传一个过大的文件或不支持的文件格式。
确认上传操作是否被正确拒绝,并且给出了恰当的错误提示信息。
测试上传和下载文件的并发性。步骤:
同时进行多个文件的上传和下载操作。
确认所有文件都可以被正常处理,没有任何冲突或错误。
以上是一些可能用于测试“往一个微信群里发文件”场景的测试用例。需要根据具体需求和软件的特定功能来进一步设计、完善测试用例。
手撕代码:阿拉伯数字转换成中国汉字(出完题人没了,也不知道上下限几位数,一脸懵逼的写完了)
def num_to_chinese(num):
# 汉字数值词典
chinese_num = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
chinese_unit = ['', '十', '百', '千']
# 将数字拆分成千百十个位上的数字
digits = [int(x) for x in str(num)]
digits.reverse()
# 数字转换成汉字
result = ''
if num == 0:
return chinese_num[0]
else:
for i, digit in enumerate(digits):
if i == 0 and digit == 0:
continue
elif digit == 0:
result = chinese_num[0] + result
else:
result = chinese_num[digit] + chinese_unit[i] + result
return result
反问:我问面试官是否一直做的是测开相关工作,您觉得测开相对于开发都有哪些区别需要具备哪些特别的能力吗?面试官说跟我无关,
我说没问题了。
可能是因为被捞的缘故,面试感觉大姐一直在从旁边电脑上找题,然后我回答完对答案,找完一个问我,我答完皱着眉头对答案,记录一下,然后再找下一个问,完全没有互动,八股不难,项目问的挺多,手撕也写出来了,但是面试体验很差劲,
第一是大姐面试我完全心不在焉,问个问题就看一边去了,也不好好听,第二是一直眉头紧皱,唉声叹气,可能是真的不想给我面试吧。所以虽然感觉问题都答得挺好的,可是还是周五准时收到感谢信,被捞那就是kpi增加下业绩了,还好当时也没报太大期望,不然又要emo好久
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
加入我的软件测试交流群:110685036免费获取~(同行大佬一起学术交流,每晚都有大佬直播分享技术知识点)
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础
获取方式 :
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。