admin管理员组

文章数量:1530838

测试开发面经总结(一)

Java当中实例化对象可以用哪些方式?

java 实例化是什么及五种实例化方法_实例化对象是什么意思-CSDN博客

简单来说,实例化对象就是new对象

new的过程就是实例化过程,比如new Cat

语法:类名 引用变量名 = new 构造器名();

调用成员属性/成员方法:引用变量名.成员名

一般是这样的,除了反射比较特殊是反着来的

方式:(5种)

1 用new语句创建对象

2 用Class类的newInstance方法,调用无参构造器创建对象

3 用Constructor类的newinstance方法(这里运用反射),调用有参的和私有的构造器对象

4 调用对象的clone()方法,

5 使用反序列化,必须先实现Cloneable接口并实现其定义的clone方法

序列化

简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自 己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

什么情况下需要序列化

a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;

b)当你想用套接字在网络上传送对象的时候;

c)当你想通过RMI传输对象的时候;

相关注意事项

a)序列化时,只对对象的状态进行保存,而不管对象的方法;

b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

d)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如:

1.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,

比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。

2. 资源分配方面的原因,比如socket,thread类,

如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。

常用的集合类有哪些?

Java集合框架主要包括两种类型的容器,一种是集合(Collection),另一种是图(Map)。Collection接口又有3种子类型,List、Set和Queue,再下面是一些抽象类,最后是具体实现类,常用的有ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap等等。Map常用的有HashMap,LinkedHashMap等。

常用的几种java集合类总结_java集合分为哪几大类-CSDN博客

开发过程中用过哪些设计模式?

面试必问的设计模式该如何回答 - 面试总结之设计模式专篇_面试中怎么聊设计模式-CSDN博客

设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案

设计模式主要分为三大类:创建型模式、结构型模式和行为型模式

单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。

太多了只能过一遍具体看链接

说一说设计模式的六大原则

开闭原则(总纲)、里氏替换原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特法则。

JDBC在数据库当中的一些增删改查操作,流程怎么样的?

JDBC增删改查(使用Java对数据库操作)_java 访问在对数据库进行增删改时需要判断返回值吗-CSDN博客

如果需要对一个数据库的表进行操作,需要那几步?

1 对数据库进行连接(不连接怎么用)

2 写sql语句

3 执行sql语句

4 关闭资源

查询操作又可以分为几步呢

1 对数据库进行连接

2 写sql语句

3 执行sql语句并得到返回值治理需要使用executeQuery()方法(因为它具有返回集的作用

对得到的结果集进行遍历输出处理

关闭资源

这里返回的结构肯定是对某一个表中的元素值进行返回,so定义一个对象来进行保存我们的结果值,顺便可以重写tostring方法进行遍历打印

改进一下:因为这样子结果只能一条语句一样的输出,so想到了使用集合来保存 每一条数据

但是集合类型不一致,所以使用泛型定义

1. 连接数据库

加载数据库驱动程序: 使用 Class.forName() 方法加载数据库驱动程序,例如:

Class.forName("com.mysql.cj.jdbc.Driver");

建立数据库连接: 使用 DriverManager.getConnection() 方法连接数据库,传入数据库 URL、用户名和密码:

String url = "jdbc:mysql://localhost:3306/mydatabase";Connection connection = DriverManager.getConnection(url, "username", "password");

2. 执行查询操作(SELECT)

创建 Statement 或者 PreparedStatement 对象: 使用 Connection 对象创建 Statement 或者 PreparedStatement 对象,用于执行 SQL 查询语句:

Statement statement = connection.createStatement();

执行 SQL 查询语句: 使用 Statement 或者 PreparedStatement 的 executeQuery() 方法执行查询操作,并获取结果集:

ResultSet resultSet = statement.executeQuery("SELECT * FROM table_name");

处理查询结果集: 遍历 ResultSet 对象,获取查询结果:

while (resultSet.next()) { // 处理每一行数据}

3. 执行插入、更新和删除操作(INSERT、UPDATE、DELETE)

创建 Statement 或者 PreparedStatement 对象: 使用 Connection 对象创建 Statement 或者 PreparedStatement 对象,用于执行 SQL 更新语句:

PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO table_name (column1, column2) VALUES (?, ?)");

设置参数并执行更新操作: 对于 PreparedStatement,设置参数后执行更新操作:

preparedStatement.setString(1, value1);preparedStatement.setString(2, value2);int rowsAffected = preparedStatement.executeUpdate();

4. 关闭资源

关闭结果集、Statement 和 Connection: 在操作结束后,关闭打开的结果集和数据库连接:

resultSet.close();statement.close();connection.close();

参考这篇:

JDBC的六大步骤(增、删、改、查的具体代码)_jdbc的查询步骤是什么,添加修改删除的步骤是什么,数据库操作对象有什么区别,getst-CSDN博客

后端可分为:控制层(controller),业务层(service),持久层(Dao)三个部分

数据库就是执行增删改查等功能

增删改为一部分,查单独为一部分

增删改:

当进行增删改操作的时候,数据从前端来,经过controller,service,Dao层,然后把数据增删改到数据库查询操作的时候与增删改相反,从数据库里面查询数据,经过这三层,在前端显示出来

查:

数据库与后端连接的过程称作JDBC的过程,(看图)数据库到Dao层就是数据库到与后端的连接过程,一共六个步骤:Dao层到service层,直接return service层到controller层,return;然后把数据送到前端显示出来

步骤:

装载驱动程序

建立连接

操作数据:创建语句,执行语句,处理结果

释放资源

用代码写一个本地的脚本,然后怎么去执行

【Linux】编写一个 shell 脚本&执行-CSDN博客

1 创建脚本文件:

首先,文本编辑器创建一个新的文件。

这个文件通常会有 .sh 的扩展名,以表明它是一个shell脚本。

创建一个名为 myscript.sh 的文件。

vim myscript.sh

2 编写脚本内容

3 保存并退出编辑器(esc + :wq)

4 为脚本添加执行权限才能执行它(chmod)

chmod +x myscript.sh(这里+a,+x等可以执行的操作字母都行吧)

5 运行脚本

./myscript.sh

SpringBoot的基本实现原理?

参考链接:

Spring Boot的工作原理-CSDN博客

核心原理:

基于spring框架,基于自动配置和约定优于配置快速构建和部署spring应用

看主类:

一个是创建SpringApplication对象,一个是调用实例的run方法

Mybatis都用过哪些注解?

mybatis常用的注解大全(持续更新)_mybatis常用注解-CSDN博客

1 增删改查类的注解

@Select

@Delete

@Insert

@Update

@Options 设置缓存时间,能够为对象生成自增的key

2 注解

@Mapper

@MapperScan

如果想要每个接口都要变成实现类,那么需要在每个接口类上加上@Mapper注解,比较麻烦,解决这个问题用@MapperScan(添加位置:是在Springboot启动类上面添加)

HTTP协议有哪些基本方法?

http1.0三种请求方法:get获取资源 post 传输实体文本 head 获得报文首部

http1.1新增方法:opnins询问支持的方法 put传输文件 patch 局部更新文件delete删除文件 trace 追踪路径connect 要求用隧道协议连接代理

GET和POST的区别?

HTTP 基础:详解 GET 和 POST 请求的关键区别_前端_Apifox_InfoQ写作社区

他们相对应的特点就是他们的区别

get请求(获取资源)-------参数会附加在url的末尾

特点:

可从服务器获取资源

参数暴露在url中 ,存在安全隐患

受url长度的限制,无法传输大量的数据

get请求具有幂等性,多次请求得到的结果相同

响应结果可被浏览器缓存

post请求(向服务器提交数据,或者创建新的资源)-----------数据会放在请求体body中 传输 而不是暴露在url里

特点:(和get对应着来)

向服务器提交数据,或者创建新的资源

不暴露在url里,参数在请求体中传输,安全隐蔽

请求体大小没有限制,可大量传输数据

post请求默认不具有幂等性,多次请求可能得到不同的结果

响应结果默认不会被浏览器缓存

如何选择 Post 请求和 Get 请求?(从他们的特点考虑)

获取资源------get

提交数据 创建新的资源 -------post

数据包含敏感信息(比如密码)或数据量大----post

要支持url收藏和分享 使用get(响应结果可被浏览器缓存)

获取资源列表: GET /resources

获取单个资源: GET /resources/:id

创建新资源: POST /resources

更新资源: PUT 或 PATCH /resources/:id(根据id更新单个)

删除资源: DELETE /resources/:id(根据id删除单个)

有没有进行过什么测试?(我做的黑马点评)

参考两篇文章:

【软件测试】Jmeter性能测试(性能测试,Jmeter使用与结果分析)_jmeter测试-CSDN博客

全网最详细的Postman接口测试教程(完整版)_postman使用开发者文档-CSDN博客

脏读,幻读,不可重复读

赃读

(我的理解)两个事务,一个事务的数据还没有提交就被另一个事务读出来了

补充:就是读到了别的事务回滚前的脏数据,比如事务B执行过程中修改了数据x,还没有提交的就被事务A读到了,而事务B却回滚了

幻读(针对insert)

(我的理解)上一次读到的数据和上一次读到的数据的数量不同

补充:当前事务读第一次取到的数据比后来读取到的数据条目少

不可重复读(针对update或delete)

后面读到的数据和之前的不一样

事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。

购物车场景设计测试用例

给你一个购物车模块,你会如何设计测试用例?【测试用例设计】_购物车设计测试用例-CSDN博客

输入url到展示界面的流程(键入网址到网页,期间发生了什么?)

非常非常常见的面试题了在哪都能看到

2.2 键入网址到网页显示,期间发生了什么? | 小林coding (xiaolincoding)

从输入URL到页面展示的详细过程(从输入url到页面展示到底发生了什么)_程序实现批量滑动打开网页到底并另存为mhtml-CSDN博客

大概流程:

1 输入url地址

2 应用层进行dns解析

3 应用层生成http请求报文

4 传输层建立TCP连接

5 网络层使用ip协议来选择路线

6 数据链路层实现网络相邻节点间可靠的数据通信

7 物理层传输数据

8 服务器处理反向传输

9 服务器返回一个HTTP响应

10 浏览器渲染

剩下的太多了看之前总结的面经和链接

什么是死锁,产生死锁的原因及必要条件

什么是死锁?死锁如何解决?-CSDN博客

什么是死锁

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

通俗一点就是

当多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进 ,这种情况就是死锁

若没有外力作用 锁死涉及到的线程都会处于永远封锁状态

死锁产生原因:

竞争资源引起进程死锁

可剥夺资源和不可剥夺资源(这个啥意思呢,可剥夺资源----->某进程获得这类资源后,这个资源可再被其他进程或系统剥夺 不可剥夺资源,当系统把这类资源分配给某进程后,再不能强行收回)

竞争不可剥夺资源

竞争临时资源

解决死锁的方法:

如果不同的程序会并发存取多个表,尽量以相同的顺序访问表,可大大降低死锁机会【就相当于维护秩序吧,避免同时并发很挤容易死锁】

在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率

对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率。

如果业务处理不好,可以用分布式事务锁或者使用乐观锁。

如何确保 N 个线程可以访问 N 个资源,同时又不导致死锁?

根据产生死锁的原因去针对性解决这个问题:

指定获取锁的顺序,并强制线程按照指定的顺序获取锁

所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了

自己设计测试用例(唉就根据日常生活来联想回答)

设计测试用例(万能思路 + 六种设计用例方法)(详细 + 图解 + 实例)-CSDN博客

万能思路:功能测试 + 界面测试 + 性能测试 + 兼容性测试 + 易用性测试 + 安全测试。

总结:

功能测试:

水杯:装水、喝水...

注册场景:注册 + 登录

想象日常使用中的注册场景有哪些功能。

界面测试:

非软件:颜色、形状、大小、材质、整体

软件:

文字/输入框/图片/下拉框 ——> 颜色、大小、形状、布局都要进行测试;

文字是否存在错别字、病句、折叠、重叠...

性能测试:

水杯:耐热性、耐寒性、耐摔性、抗压性...

软件:

响应时间

几千万人同时访问...

兼容性测试:

水杯:水杯可以装液体,针对不同液体。

软件:

系统:Linux、Windows、Mac;

终端:PC、移动端

浏览器:Chrome、FireFox、Safari...

易用性测试:

需要具备便捷、简单易上手的属性,用户引导、符合用户使用习惯。

安全测试:

水杯:

水杯的材质是否安全;

特殊情况下(高温低温)材质是否会释放毒性;

存放特殊的液体会不会导致化学反应,材质是否会释放毒性;

软件:

SQL注入

XSS漏洞

越权(垂直越权、水平越权)

等价划分法:将所有可能的输入数据划分成若干个等价类,从等价类中选出一个测试用例,如果这个测试用例通过,就认为这个等价类通过(就相当于等分然后随机取样来检测局部测试结果就代表整个测试结果了)

有效等价类(合理的、有意义)

无效等价类(无意义的)

还有一个边界值,判定表法

Java创建线程的方式

自己公众号做过的笔记:

终于学到进程线程部分了!!!

一 ,继承于Thread类

步骤:

1.创建一个继承于Thread类的子类

2.重写Thread类的run() --> 将此线程执行的操作声明在run()中

3.创建Thread类的子类的对象

4.通过此对象调用start()执行线程

二 实现Runnable 接口

创建一个实现了Runnable接口中 的类

实现类去实现Runnable 的抽象方法 run()

创建实现类的对象

将此对象作为参数传递到Thread类的构造器中 创建Thread类

通过Thread类的对象调用start()

1 启动线程

2 调用当前线程的run() 调用Runnable类型 的target 的run()

三 ,实现Callable接口

步骤:

1.创建一个实现Callable的实现类

2.实现call方法,将此线程需要执行的操作声明在call()中

3.创建Callable接口实现类的对象

4.将此Callable接口实现类的对象作为传递到FutureTask构造器中,创建FutureTask的对象

5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()

6.获取Callable中call方法的返回值

四 使用线程池

五 使用匿名类

反射

Java基础之—反射(非常重要)-CSDN博客

反射就是把java类中的

各种成分映射成一个个的java对象(就如同照镜子一样)

呃就是在运行状态中对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意方法和属性。就是反射(都知道都能调用)

获取class对象的三种方式

Object———>getClass()

任何数据类型都有一个“静态”的class属性

通过class类的静态方法 forName(String className)

黑盒白盒测试

黑白测试与白盒测试及其方法-CSDN博客

白盒测试(结构测试)就是程序员因为状态不好或者对工具的使用不熟练造成的代码问题,对这些问题进行测试

补:白盒是可视的,清楚盒子内部的东西以及以及里面是如何运作的,黑盒是不可视的,

黑盒测试就是对功能进行测试,通过测试来检测每个功能是否能正常使用

测试中把程序看作一个不能打开的黑盒

在完全不考虑程序内部结构和内部特性的情况下,在程序接口进行测试

什么是装饰器(python里面的内容)

python语言的一种特性

它允许在 不修改已有函数 的情况下,向函数 添加帧外 的功能。

装饰器本质上是一个函数,它接受一个函数作为参数,并返回新的函数

本质函数 接受函数做参数 返回新的函数

什么是单例模式

什么是单例模式?单例模式有什么作用?为什么要用单例模式_单例模式的作用-CSDN博客

设计模式里面最简单的一种,我只记得这个

首先它是创建型模式

其次它涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建

单例类———->只能有一个实例

单例类————>必须自己创建自己的唯一实例

必须给其他所有对象提供这一实例

如果在系统中不使用单例模式的话,在碰请到多线程访问的时候,printer就会给要求的类,分别在内存中new出一个printer对象,让这些请求的类去做print方法。这样大量占有内存,就会导致系统运行变慢,像电脑的CPU一样,占有量极高,电脑卡死不动的感觉。

因为系统的硬件设施需求变动量小,所以只能想出一个节约成本 的方法就是,单例模式,让多线程处于等待的状态,一个 一个的去解决,这样,即节约内存,提交了运行的成本。也就是单例存在的意义

Python如何实现多线程

Python中线程与进程_python爬虫的线程进程-CSDN博客

看下面这个

### 1. 导入 threading 模块

首先,需要导入 Python 的 threading 模块:

import threading

### 2. 定义线程执行的函数

创建一个函数,这个函数包含了线程将要执行的任务。例如:

def task(thread_name):

print(f"Thread {thread_name} is running")

这个函数接受一个参数 thread_name,用于显示线程的名称。

### 3. 创建线程对象

使用 threading.Thread 类创建线程对象,指定要运行的函数和参数。例如,创建两个线程:

thread1 = threading.Thread(target=task, args=("Thread-1",))

thread2 = threading.Thread(target=task, args=("Thread-2",))

### 4. 启动线程

通过调用线程对象的 `start()` 方法来启动线程:

thread1.start()

thread2.start()

### 5. 等待线程结束

如果需要等待线程执行完毕,可以使用 join() 方法:

thread1.join()

thread2.join()

这样主线程会等待 `thread1` 和 `thread2` 执行完毕后再继续执行。

### 解释

- task 函数模拟了线程要执行的任务,这里简单地打印线程名,并休眠 2 秒钟。

- 创建了两个线程 thread1 和 thread2,分别执行 task 函数。

- thread1.start() 和 thread2.start() 启动了这两个线程。

- thread1.join() 和 thread2.join() 确保主线程等待 thread1 和 thread2 执行完成后再继续执行。

并行与并发

并发:有处理多个任务的能力,不一定同时处理

并行;有同时处理多个任务的能力

进程和线程的关系:

一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。(即所属关系)

资源分配给进程,同一进程的所有线程共享该进程的所有资源。

CPU分给线程,即真正在CPU上运行的是线程。

Python的垃圾回收机制

python面试题7:Python垃圾回收机制(难度--中等)-CSDN博客

垃圾回收机制是一个复杂的系统,用于管理不在使用的内存(垃圾回收嘛),防止内存泄漏并提高程序的性能,通常由引用计数,标记–清除,分代收集算法来处理循环引用等问题。

1 引用技术

2 标记-清除

通常分为两个阶段:

第一 阶段从根对象出发,遍历所有可达对象的“活动对象”并打击对象

第二阶段清除阶段,释放所有未标记对象的空间

3 分代收集

对于新对象进行高频率的检查,老对象则采用低频率检查,因而往往新对象更容易成为垃圾。

主要目的是为了减少垃圾回收的开销。

TCP/UDP区别

TCP面向连接 UDP不面向连接

TCP可靠传输 UDP不可靠,尽最大努力交付

TCP面向字节流 UDP面向数据报文

TCP支持点对点通信 UDP一对一,一对多,多对多

TCP报文首部20个字节,TCP报文首部8个字节

TCP有拥塞控制机制 UDP没有

TCP协议下双方发送接受缓冲区都有,UDP并无实际意义上的发送缓冲区,但是存在接受缓冲区

HTTP/HTTPS区别

HTTPS和HTTP的区别主要如下:

  1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

  2、http是超文本传输协议,信息是明文传输; https则是具有安全性的ssl加密传输协议。

  3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

  4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

TCP三次握手和四次挥手,以及中间就是会怎样

简单理解TCP三次握手四次挥手(看一遍你就懂)-CSDN博客

最开始的时候客户端和服务器都是处于CLOSED关闭状态。主动打开连接的为客户端,被动打开连接的是服务器。

TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了 LISTEN 监听状态

第一次握手 TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT 同步已发送状态

第二次握手 TCP服务器收到请求报文后,如果同意连接,则会向客户端发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了 SYN-RCVD 同步收到状态

第三次握手 TCP客户端收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED已建立连接状态 触发三次握手

有人可能会很疑惑为什么要进行第三次握手?

主要原因:防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误

第一次握手: 客户端向服务器端发送报文

证明客户端的发送能力正常

第二次握手:服务器端接收到报文并向客户端发送报文

证明服务器端的接收能力、发送能力正常

第三次握手:客户端向服务器发送报文

证明客户端的接收能力正常

如果采用两次握手会出现以下情况:

客户端向服务器端发送的请求报文由于网络等原因滞留,未能发送到服务器端,此时连接请求报文失效,客户端会再次向服务器端发送请求报文,之后与服务器端建立连接,当连接释放后,由于网络通畅了,第一次客户端发送的请求报文又突然到达了服务器端,这条请求报文本该失效了,但此时服务器端误认为客户端又发送了一次连接请求,两次握手建立好连接,此时客户端忽略服务器端发来的确认,也不发送数据,造成不必要的错误和网络资源的浪费。

如果采用三次握手的话,就算那条失效的报文发送到服务器端,服务器端确认并向客户端发送报文,但此时客户端不会发出确认,由于客户端没有确认,由于服务器端没有接收到确认,就会知道客户端没有请求连接。

TCP四次挥手

建立TCP连接需要三次握手,终止TCP连接需要四次挥手

举个例子

张三和李四的对话

张三:好的,那我先走了

李四:好的,那你走吧

李四:那我也走了?

张三:好的,你走吧

第一次挥手 客户端发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态

第二次挥手 服务器端接收到连接释放报文后,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT 关闭等待状态

第三次挥手 客户端接收到服务器端的确认请求后,客户端就会进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文,服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态,但此时TCP连接还未终止,必须要经过2MSL后(最长报文寿命),当客户端撤销相应的TCB后,客户端才会进入CLOSED关闭状态,服务器端接收到确认报文后,会立即进入CLOSED关闭状态,到这里TCP连接就断开了,四次挥手完成

测试开发面经总结(二)

为什么做这个项目以及参考了什么

参考:

【项目】如何在面试中介绍自己的项目经验(附如何解决未知的问题&成长路线)_面试如何做项目介绍-CSDN博客

从事测开岗位的优势

自学能力强,思维敏捷,会编程语言python,java等

给你一个全新的APP该怎么测试

参考:

给你一个app你如何展开测试?_拿到一个 app 怎么做软件测试-CSDN博客

从这几个方面说一下即可:

功能测试

登录界面测试

看用手机号和密码登录跳转需要多长时间

性能测试

适配兼容测试

服务器性能测试

安全测试

UI测试

安装/卸载测试

怎么利用大语言模型怎么做测试

参考:

大语言模型应用后如何测试

输入一个ur到页面展示的全过程

简略版:面试题:从输入网址到网页显示,期间发生了什么? - April的个人站

一、HTTP

浏览器首先解析URL,确定发给web服务器的请求信息,根据请求信息生成对应的HTTP请求报文。

二、DNS

在大多数情况下都是通过域名而不是IP地址来获取信息,因此还需要将URL中的域名转换为对应的IP地址。一般来说,浏览器会先查看自身缓存,如果缓存中存在该域名对应的IP地址,就直接使用,如果不存在,会发送请求到DNS服务器获取。

域名是存在层级关系的,通过点号分隔,越靠右级别越高。每个DNS服务器只对应一个层级,形成一个树状结构。

以查找www.baidu的IP地址为例。

本地DNS服务器首先发送查询请求到根DNS服务器

根DNS服务器发现后缀为,返回()DNS服务器的地址

本地DNS服务器根据返回的地址发送查询请求到()DNS服务器

()DNS服务器发现二级后缀为.baidu,返回(.baidu)服务器地址...

就这样一级一级,直到找到对应的IP地址。

三、TCP

获得完整的HTTP请求后,浏览器会调用socket库委托协议栈工作。协议栈根据需求选择使用TCP或者UDP。

如果选择使用TCP,需要在数据发送前通过三次握手与服务端建立连接。

除此之外,还要生成TCP报文。如果数据量较大的话,还需要进行数据分割。

最后得到封装了HTTP数据的TCP数据包。

四、IP

在TCP数据包的基础上,封装源地址IP和目标地址IP等信息,得到网络包。在网络中跳转传输的过程中就需要IP数据来确认该将数据发送到哪里。

五、MAC

如果说IP头部是指导数据在多节点的网路中如何传输,MAC头就是确保设备两点之间的通信。MAC头中存储了发送方的MAC地址,以及接收方的MAC地址(通过ARP协议获取)。

六、网卡

在此之前,网络包还只是存储在内存中的二进制数据。网卡将二进制数据转换为电信号,再通过网线传输。

七、交换机

在交换机中会校验数据包是否出错,并根据数据包中的MAC头判断该转发到哪个具体的端口,如果交换机中的MAC地址表没有对应信息,则会向所有端口广播。

八、路由器

交换机的下一步是路由器。路由器也是进行转发,但是是IP层面的。与交换机不同,路由器的各个端口都具有MAC地址和IP地址,也就是说,路由器是接入到以太网中的。

数据在路由器中不断转发,最后到达服务端。

九、服务端与客户端

当服务端获取数据包后,按逆序一层层去掉协议头,就能获得原请求数据了。

Spring bean 是线程安全的吗

不安全

Spring框架中的Bean是线程安全的吗?如果线程不安全,要如何处理?_bean的请求(request)作用域是线程安全的吗-CSDN博客

Spring(十一):Spring Bean 是线程安全的吗? - 光星の博客

数组怎么快速拷贝

Java系列 之 Java复制(拷贝)数组的4种方法:arraycopy()方法、clone() 方法、copyOf()和copyOfRan_java array copy-CSDN博客

说一下你熟悉的Linux、maven命令

面试题:说说maven 以及打包命令_maven package 打包命令-CSDN博客

mvn clean pacage

mvn clean install

mvn clean deploy

区别

package 命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

install 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库

deploy 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

动态sql的优点

mybatis动态SQL语句的优缺点:_动态sql的优缺点-CSDN博客

简单学习一下 MyBatis 动态SQL使用及原理_Java_做梦都在改BUG_InfoQ写作社区

数据库锁机制

5.5 什么是悲观锁、乐观锁? | 小林coding (xiaolincoding)

MySQL数据库的锁 --- 六种分类 - 14种锁详细介绍_mysql的锁-CSDN博客

【数据库】数据库的锁机制及原理_sql server 数据库锁死-CSDN博客

数据库锁

互斥锁,自旋锁,读写锁,悲观锁,乐观锁

其中互斥锁,自旋锁,读写锁都属于悲观锁

悲观锁

比较悲观,他认为多线程可能会同时修改共享数据资源,容易造成冲突,所以在访问共享资源之前,都会先上锁

乐观锁:

就比较乐观,他认为造成冲突的概率比较低,所以不管三七二十一,先把共享数据资源全部修改完成后,才去看之前有没有其他线程修改过共享数据,没有则操作完成,有则放弃本次操作

对于乐观锁来说如果有造成冲突,则需要重试,重试造成的成本消耗还是挺大的

所以一般什么情况下会使用乐观锁呢?

在冲突产生概率非常低且加锁成本非常高的情况下就考虑用乐观锁

为什么这么说?------------>因为乐观锁全程不用加锁

乐观锁场景用例

在线文档。比如班群里发了一个在线文档,班里同学都能同时去编辑那个文档,这就是用到了乐观锁。不能要一个同学编完了下一个同学才能去编辑吧,这样确实挺气人的。

怎样才算冲突呢?

比如用户 A 先在浏览器编辑文档,之后用户 B 在浏览器也打开了相同的文档进行编辑,但是用户 B 比用户 A 提交早,这一过程用户 A 是不知道的,当 A 提交修改完的内容时,那么 A 和 B 之间并行修改的地方就会发生冲突。

说一下互斥锁,自旋锁,读写锁

互斥锁:线程a获得锁,则线程b只能释放CPU,切换给其他线程,自己先进入睡眠状态,当线程a释放锁,唤醒线程b,线程b就要切换回来CPU,这个就是上下文线程切换,消耗一定的性能

互斥锁加锁失败后,线程会释放 CPU ,给其他线程;

自旋锁加锁失败后,线程会忙等待,直到它拿到锁;

读写锁:分为读锁和写锁,读锁是共享的,写锁是独占的(就是指允许一个线程拿到锁)

比如线程a获取读锁,线程b获取读锁,一直都是读锁停不下来,那写锁一直拿不到锁,就很不公平,同如果一直是写锁,读锁也根本进不来

所以解决办法:

公平读写锁:采用队列的方式,先进先出

补充:一般加锁的过程:查看锁的状态,如果锁是空闲的,则将锁设为持有状态

测试开发面经总结(三)

TCP三次握手

TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。

一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态

客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。

服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。

客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务端的数据,之后客户端处于 ESTABLISHED 状态。

服务端收到客户端的应答报文后,也进入 ESTABLISHED 状态。第三次握手是可以携带数据的,前两次握手是不可以携带数据的

一旦完成三次握手,双方都处于 ESTABLISHED 状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。

TCP的第一次握手在什么情况下,服务端会没有响应

在TCP协议中,第一次握手是指客户端发送一个SYN(同步)包到服务端,用于请求建立连接。在正常情况下,服务端收到SYN包后应该会回复一个SYN-ACK(同步-确认)包,表示同意建立连接。然后客户端再回复一个ACK(确认)包,建立连接成功。

服务端没有响应第一次握手的情况通常有几种可能的原因:

网络问题:可能是由于网络中的故障或者丢包导致服务端没有收到客户端发送的SYN包。

服务端负载过重:如果服务端处于高负载状态,处理不及时,可能会导致无法及时响应客户端的SYN包。

防火墙或网络设备过滤:某些防火墙或者网络设备可能会过滤或者延迟某些TCP包的传输,导致服务端没有收到客户端的SYN包。

服务端端口未监听:如果客户端尝试连接的服务端端口没有在服务端上监听(即没有应用程序在该端口上等待连接),服务端会忽略或者拒绝客户端的连接请求。

Linux如何通过命令查看日志文件的某几行(中间几行或最后几行)

linux 如何显示一个文件的某几行(中间几行)

【一】从第3000行开始,显示1000行。即显示3000~3999行

cat filename | tail -n +3000 | head -n 1000

cat filename: 打开 filename 文件并将其内容输出到标准输出(通常是显示屏)。

tail -n +3000: tail 命令用于从文件末尾开始显示,-n +3000 表示从第3000行开始显示到文件末尾。

head -n 1000: head 命令用于从文件开头显示,默认为显示前10行,-n 1000 表示显示前1000行。

因此,这条命令的组合作用是先将文件 filename 从第3000行开始的内容输出,然后再从这个输出中取前1000行显示出来。

【二】显示1000行到3000行

cat filename | head -n 3000 | tail -n +1000

那作为测试工程师我们的职责有哪些呢?

软件测试工程师简单的说是软件开发过程中的质量检测者和保障者,负责软件质量的把关工作。

主要职责有:编写测试计划,编写测试用例,搭建测试环境,执行测试,进行bug验证根据测试结果分析,完成上级及部门以及领导交办的任务...这些均需要我们具备良好的学习能力。

进程和线程的区别

1. 进程是一个运行的程序,是系统进行资源调度和分配的一个独立单位,进程中包含了线程,每个线程执行不同的任务。

2. 不同进程使用的内存空间是不同的,同一个进程下的线程共享内存空间。

3. 线程更加轻量,上下文切换的成本比进程要低。

4.对Python有哪些了解

Python是一种解释型语言。与C语言等语言不同,Python不需要在运行之前进行编译。

Python是动态语言,当您声明变量或类似变量时,您不需要声明变量的类型。

Python适合面向对象的编程,因为它允许类的定义以及组合和继承。Python没有访问说明(如C ++的public,private)。

在Python中,函数是第一类对象。它们可以分配给变量。类也是第一类对象

编写Python代码很快,但运行比较慢。Python允许基于C的扩展,例如numpy函数库。

Python可用于许多领域。Web应用程序开发,自动化,数学建模,大数据应用程序等等。

5.Python有哪些数据结构

列表list:有序,可变的集合

元组Tuple:有序,不可变的集合

字典Dictionary:无序的键值对集合

集合set:无序,不重复的集合、

字符串:String,不可变的字符序列

列表和元组的区别是什么

列表是动态数组,它们可变且可以重设长度(改变其内部元素的个数)。

元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。

元组缓存于Python运行时环境,这意味着我们每次使用元组时无须访问内核去分配内存。

这些区别结实率两者在设计哲学上的不同:

列表可被用于保存多个互相独立对象的数据集合

元组用于描述一个不会改变的事务的多个属性

两张表,查询出学生的成绩>80的姓名以及成绩

假设两张表,Students和Grades,其中 Students 表存储学生信息,Grades 表存储学生成绩信息,它们可能通过学生的ID关联。假设学生成绩存储在 Grades 表中,包括学生的ID和成绩,学生的姓名存储在 Students 表中,包括学生的ID和姓名:

select Students.name, Grades.grade from Students join Grades on Students.student_id = Grades.student_id where Grades.grades >80;

Students.student_id 和 Grades.student_id 是关联两张表的外键关系

Students join Grades on表示要将 Students 表和 Grades 表连接起来,形成一个更大的结果集,该结果集将包含两张表的相关信息。

你觉得测开的工作内容是什么

我自己下去大概了解了一下,就是测试和开发

1)业务质量保障:

2)工具平台开发:

3)专项测试/用户体验评测:

4)质量运营:

1)业务质量保障:参与业务需求分析、技术方案评审、可测性分析、测试方案设计、测试项目管理、性能压测、安全性测试、自动化实施、流水线建设、代码覆盖率分析、静态代码扫描及其他质量特性测试等 2)工具平台开发:自动化测试框架、流量回放平台、质量度量管理平台、事故管理分析平台、云测平台等 3)专项测试/用户体验评测:App性能评测、竞品分析、音视频专项、安全专项、稳定性专项等 4)质量运营:事故分析、质量报告、质量文化建设、bug治理、质量大盘建设等。

不论哪个方向,代码能力都是非常重要的准入门槛,2、3对算法等技术能力要求更高;1更偏向于测试管理方向;4需要具备敏锐的观察力、沟通交流以及push能力和创造性,能通过数据挖掘质量保障及研发流程、项目团队管理、技术方案等中的问题,并推进落实解决。

tcp/ip

网络接口层 网络层 传输层 应用层

域名解析过程

客户端首先会发出一个 DNS 请求,问 www.server 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。

本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大, 能告诉我 www.server 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。

根 DNS 收到来自本地 DNS 的请求后,发现后置是 ,说:“www.server 这个域名归 区域管理”,我给你 顶级域名服务器地址给你,你去问问它吧。”

本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二, 你能告诉我 www.server 的 IP 地址吗?”

顶级域名服务器说:“我给你负责 www.server 区域的权威 DNS 服务器的地址,你去问它应该能问到”。

本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server对应的IP是啥呀?” server 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。

权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。

本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接。

至此,我们完成了 DNS 的解析过程。

http响应码

200 - 请求成功

301 - 资源(网页等)被永久转移到其它URL

404 - 请求的资源(网页等)不存在

500 - 内部服务器错误

HTTP状态码分为五类:信息响应 (100–199),成功响应 (200–299),重定向 (300–399),客户端错误 (400–499)和服务器错误 (500–599)

死锁的产生

可归结为如下两点:

1)竞争资源;

2)进程间推进顺序非法;

a. 竞争资源:

系统中的资源可以分为两类:

可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程夺走,比如:CPU就属于可剥夺性资源;

不可剥夺资源,是指当系统把这类资源分配给某进程后,不能再强制收回,只能在进程将任务完成后、自行释放,比如:磁带机、打印机等。

本文标签: 最全测试