成功拿到B站测开岗年薪50W+offer,面经分享

一面

首先,自我介绍,我介绍了自己的技术栈和项目。

技术栈提到过Spring、Redis、Kafka、Docker、K8s、大数据。

项目提到过接口和UI自动化。

我有个大数据平台项目,问了比较多,聊着聊着,提到自己研究过Selenium、TestNg源码,让我讲讲研究的心得,就扩展性地聊了下,其实在面试之前,已经想到面试官会问。

下面一些知识点提问:

1、Jmeter 调参,遇到过什么疑难问题

JMeter 是一款功能强大的压力测试工具,但是在调参时也可能会遇到一些疑难问题。以下是一些可能遇到的问题及解决方法:

1、线程组设置不当,导致性能测试结果不准确:线程组的配置包括线程数、循环次数等,如果设置不当会导致测试结果不准确。建议根据实际情况调整线程数和循环次数,以达到更好的测试效果。

2、调整并发数时,可能会出现服务器负载过高或过低的问题:调整并发数时需要根据服务器的实际负载情况进行调整,以免过高或过低造成测试结果不准确。可以使用监控工具对服务器负载进行实时监控,以便及时进行调整。

3、JMeter 配置不当,导致测试结果出现误差:JMeter 的配置包括连接超时时间、响应超时时间、HTTP 头等,如果设置不当会导致测试结果出现误差。建议根据实际情况进行配置,以达到更准确的测试结果。

4、JMeter 性能不足,无法满足测试需求:如果 JMeter 的性能无法满足测试需求,可以考虑使用分布式测试或其他性能测试工具,以提高测试效率和准确性。

5、接口调用时出现异常,导致测试结果出现误差:如果接口调用时出现异常,可能会导致测试结果出现误差。建议在测试前先对接口进行稳定性测试,以确保接口的可靠性和稳定性。

总之,在进行 JMeter 调参时,需要根据实际情况进行合理的配置和调整,以达到更准确的测试结果。

2、讲一下在项目中 Docker 运用

1、Docker 是一种容器化技术,可以将应用程序及其依赖项打包成一个独立的容器,在不同的环境中进行快速部署和运行。在项目中,Docker 可以用于以下方面:

2、应用程序部署:使用 Docker 可以将应用程序及其依赖项打包成一个独立的容器,方便在不同的环境中进行部署和运行,避免因环境差异导致的问题。

3、持续集成和持续部署(CI/CD):Docker 可以与 CI/CD 工具(如 Jenkins、GitLab CI 等)结合使用,实现自动化构建、测试和部署,加快交付速度。

4、依赖项管理:Docker 可以将应用程序的依赖项打包到容器中,避免在不同的环境中手动安装依赖项的麻烦。

5、多版本管理:使用 Docker 可以在同一台机器上同时运行多个版本的应用程序,方便进行版本管理和测试。

6、安全性:Docker 提供了一些安全机制,如容器隔离、访问控制等,可以保障应用程序的安全性。

在实际项目中,Docker 的运用方式因项目的特点而异,但总的来说,Docker 可以提高应用程序的部署、运行和管理效率,从而加速项目的开发和交付。

3、K8s 里 node 和 pod 是什么关系

1、在 Kubernetes 中,Node 和 Pod 之间存在着一种父子关系。Node 是 Kubernetes 集群中的一个工作节点,负责承载 Pod 的运行,而 Pod 是 Kubernetes 中最小的调度单元,可以理解为一个容器的逻辑宿主机。

2、Node 是 Kubernetes 集群中的一个物理或虚拟机器,具有足够的计算、存储和网络资源,可以运行一些容器应用。Kubernetes 会将 Pod 调度到可用的 Node 上,以实现应用程序的高可用和负载均衡。在一个 Node 上,可以运行多个 Pod,每个 Pod 里面可以运行一个或多个容器,这些容器可以共享同一个网络空间和存储空间,方便它们之间的通信和数据共享。

3、一个 Pod 只能运行在一个 Node 上,但一个 Node 上可以运行多个 Pod。Kubernetes 会根据应用程序的需求,将多个 Pod 分配到不同的 Node 上,以实现负载均衡和容错能力。

总之,Node 是 Kubernetes 集群中的工作节点,负责承载 Pod 的运行;而 Pod 是 Kubernetes 中最小的调度单元,包含一个或多个容器,可以共享同一个网络空间和存储空间。Node 和 Pod 之间存在着一种父子关系,一个 Node 上可以运行多个 Pod,每个 Pod 只能运行在一个 Node 上。

4、顺序表和链表有什么区别

顺序表和链表都是常用的线性数据结构,但它们有以下区别:

存储结构不同:顺序表采用连续的内存空间存储元素,可以随机访问任意一个元素;而链表则采用链式存储结构,每个元素都包含一个指向下一个元素的指针,不能随机访问。

插入和删除操作的效率不同:顺序表中插入和删除一个元素需要移动其他元素的位置,时间复杂度为 O(n);而链表中插入和删除一个元素只需要改变指针指向的位置,时间复杂度为 O(1)。

随机访问的效率不同:由于顺序表的元素是连续存储的,所以随机访问一个元素的时间复杂度为 O(1);而链表中的元素是分散存储的,随机访问一个元素需要从头节点开始遍历到该节点,时间复杂度为 O(n)。

空间复杂度不同:顺序表的空间复杂度为 O(n),因为它需要预先分配足够的内存空间来存储所有元素;而链表的空间复杂度为 O(n),因为它只需要为每个元素分配必要的内存空间。

总之,顺序表适用于元素数量不太变化、需要频繁随机访问的场景,而链表适用于元素数量频繁变化、需要频繁插入和删除操作的场景。

5、冒泡排序的时间复杂度,为什么是这个时间复杂度?(其实就是考察冒泡的思想)

冒泡排序的时间复杂度为 O(n^2),其中 n 表示待排序元素的个数。

冒泡排序是一种比较简单的排序算法,它的基本思想是每次比较相邻的两个元素,如果它们的顺序不对,则交换它们的位置,通过多次遍历和比较,将待排序的序列逐渐变为有序序列。具体的实现步骤如下:

从序列的第一个元素开始,依次比较相邻的两个元素,如果它们的顺序不对,则交换它们的位置。

继续对序列中的剩余元素进行相同的比较和交换,直到遍历到序列的最后一个元素。

重复步骤 1 和步骤 2,直到整个序列都变成有序序列。

由于每次排序都需要遍历整个序列,比较相邻的元素并交换它们的位置,所以冒泡排序的时间复杂度为 O(n^2)。即在最坏情况下,需要进行 n-1 次遍历,每次遍历需要比较 n-i 次相邻元素并进行一次交换,总的时间复杂度就是 n*(n-1)/2,即 O(n^2)

虽然冒泡排序的时间复杂度较高,但是它的实现简单易懂,适用于数据量较小的排序场景。在实际应用中,可以采用其他排序算法,如快速排序、归并排序等,来提高排序效率。

6、Spring Bean 的生命周期

Spring Bean 的生命周期可以分为以下阶段:

实例化:在 Spring 容器启动时,根据配置文件或注解等方式,创建 Bean 的实例。

属性赋值:对 Bean 实例的属性进行赋值,包括通过 setter 方法或注解方式进行赋值。

Aware 接口回调:调用 Bean 实现了 Spring Aware 接口的回调方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 等,使 Bean 能够获取 Spring 容器的相关信息。

BeanPostProcessor 前置处理器:在 Bean 初始化前,执行实现了 BeanPostProcessor 接口的前置处理器的方法,对 Bean 进行处理,如添加代理等。

初始化:调用 Bean 实现了 InitializingBean 接口的 afterPropertiesSet 方法和 Bean 配置文件中的 init-method 方法进行 Bean 的初始化操作。

BeanPostProcessor 后置处理器:在 Bean 初始化后,执行实现了 BeanPostProcessor 接口的后置处理器的方法,对 Bean 进行处理,如添加代理等。

使用:当 Bean 实例化并初始化完成后,可以被其他对象引用并使用。

销毁:在 Spring 容器关闭时,调用 Bean 实现了 DisposableBean 接口的 destroy 方法和 Bean 配置文件中的 destroy-method 方法进行 Bean 的销毁操作。

需要注意的是,可以通过实现 BeanPostProcessor 接口来对 Bean 进行前置和后置处理,也可以通过实现 InitializingBean 和 DisposableBean 接口或配置 init-method 和 destroy-method 方法来进行 Bean 的初始化和销毁操作。但是建议使用后一种方式,因为它更加灵活,可以在配置文件中指定初始化和销毁方法,而不是硬编码在代码中。

7、Linux 查看端口

在 Linux 系统中,可以使用以下命令来查看端口:

netstat 命令:可以查看当前正在运行的所有进程的网络状态信息,包括监听的端口、连接状态等。

$ netstat -ano | grep LISTEN

其中,“-a” 表示显示所有连接和监听端口,“-n” 表示使用数字形式显示端口号,“-o” 表示显示进程 ID。

lsof 命令:可以列出所有打开的文件,包括网络连接、进程、端口等。

$ lsof -i :端口号

8、算法题:比较版本号

public static int compareVersion(String version1, String version2) {
   
       String[] arr1 = version1.split("\\.");    String[] arr2 = version2.split("\\.");    int len = Math.max(arr1.length, arr2.length);    for (int i = 0; i < len; i++) {
   
           int v1 = i < arr1.length ? Integer.parseInt(arr1[i]) : 0;        int v2 = i < arr2.length ? Integer.parseInt(arr2[i]) : 0;        if (v1 > v2) {
   
               return 1;        } else if (v1 < v2) {
   
               return -1;        }    }    return 0;}

比较版本号的算法可以按照以下步骤进行:

1、将版本号字符串按照“.”进行分割,得到版本号数组。

2、将版本号数组转换为数字类型,可以使用 parseInt 或者 Number 等方法将每个子版本号转换为数字类型。

3、比较每个子版本号的大小,从左到右逐一比较,如果前面的子版本号相等,则比较后面的子版本号。

4、如果一个版本号的子版本号比另一个版本号的子版本号多,则将缺少的子版本号视为 0。

5、如果比较到最后,所有的子版本号都相等,则认为两个版本号相等。

6、如果比较到最后,某个子版本号大于另一个版本号的相应子版本号,则认为该版本号比另一个版本号大。

二面

1、自我介绍

作为一名测试开发工程师,我通常负责开发和维护测试框架、自动化测试脚本和工具,以确保软件在开发过程中质量的稳定性和可靠性。我的工作不仅仅是编写测试脚本,而是通过深入了解业务需求和产品功能,设计测试用例、测试方案和测试策略,进行自动化测试和手动测试,并对测试结果进行分析和反馈,帮助团队提高测试效率和产品质量。

我熟悉多种测试框架和工具,如Selenium WebDriver、JUnit、TestNG、Appium、Rest-Assured等。我具备Java或Python等编程语言的开发经验,能够独立完成测试脚本和测试工具的开发,也能够通过集成Jenkins、Git等工具进行持续集成和持续交付。

此外,我注重团队协作和沟通,善于与开发人员、产品经理、项目经理等不同角色的人员合作,理解业务需求和产品目标,为团队提供有价值的测试建议和技术支持,促进项目进展和成功。

总之,我是一名具有扎实的测试技术基础和热情的测试开发工程师,对软件质量和用户体验有着高度的责任感和使命感,期待在您的团队中发挥我的技术和专业能力。

2、项目技术架构、业务功能

项目技术架构和业务功能项目相关

在软件开发中,技术架构是指软件系统的整体设计,包括系统的组成部分、各部分之间的交互方式、使用的技术工具等方面。下面是一个通用的软件项目技术架构,其中包含了多种常见的技术组件:

前端技术:

HTML/CSS

JavaScript

React/Vue.js/Angular

后端技术:

编程语言:Java/Python/Node.js/C#等

Web框架:Spring/SpringBoot/Django/Flask等

数据库:MySQL/Oracle/PostgreSQL/MongoDB等

消息队列:RabbitMQ/Kafka等

缓存:Redis/Memcached等

部署和运维技术:

Docker/Kubernetes等容器化技术

CI/CD工具:Jenkins/Gitlab CI/Travis CI等

监控:Prometheus/Grafana等

日志:ELK Stack/Graylog等

当然,不同的项目可能会使用不同的技术架构,具体的架构应该根据实际情况进行选择。

Redis 持久化、如何保证缓存中的数据持续有效命中

Redis提供了两种持久化方式,分别是RDB持久化和AOF持久化。其中,RDB持久化是将内存中的数据定期保存到磁盘上,而AOF持久化则是将每个写操作追加到一个日志文件中,这样可以保证在Redis服务器崩溃或重启时,数据不会丢失。

除了持久化,还有一些其他的方式可以保证缓存中的数据持续有效命中:

设置合适的过期时间:可以根据业务需要设置缓存的过期时间,保证缓存中的数据不会长时间存在,避免数据过期而无法使用。

LRU算法:Redis使用LRU算法来淘汰长时间未被使用的缓存数据,以保证内存空间不会被耗尽。

冷热数据分离:将访问频率较低的数据移至磁盘上,访问频率高的数据保留在内存中,可以减少内存的占用,提高命中率。

使用Redis Cluster:Redis Cluster可以将数据分布到多个节点上,增加了Redis的容错性和可用性,减少了单节点宕机导致数据不可用的风险。

综上所述,通过合理的持久化方式、设置合适的过期时间、LRU算法、冷热数据分离以及Redis Cluster的使用等方式,可以有效保证缓存中的数据持续有效命中。

3、算法:反转链表

class Listnode {
   
       int val;    ListNode next;

    ListNode(int val) {
   
           this.val = val;    }}
class Solution {
   
       public ListNode reverseList(ListNode head) {
   
           ListNode prev = null;        ListNode curr = head;        while (curr != null) {
   
               ListNode nextTemp = curr.next;            curr.next = prev;            prev = curr;            curr = nextTemp;        }        return prev;    }}
ListNode head = new ListNode(1);head.next = new ListNode(2);head.next.next = new ListNode(3);head.next.next.next = new ListNode(4);head.next.next.next.next = new ListNode(5);
Solution solution = new Solution();ListNode reversedHead = solution.reverseList(head);

while (reversedHead != null) {
   
       System.out.print(reversedHead.val + " ");    reversedHead = reversedHead.next;}// 输出:5 4 3 2 1

二叉树后序遍历

class TreeNode {
   
       int val;    TreeNode left;    TreeNode right;

    TreeNode(int val) {
   
           this.val = val;    }}

class Solution {
   
       public List<Integer> postorderTraversal(TreeNode root) {
   
           List<Integer> result = new ArrayList<>();        postorderTraversalHelper(root, result);        return result;    }

    private void postorderTraversalHelper(TreeNode root, List<Integer> result) {
   
           if (root == null) {
   
               return;        }        postorderTraversalHelper(root.left, result);        postorderTraversalHelper(root.right, result);        result.add(root.val);    }}

在这个实现中,我们使用递归函数来遍历二叉树。首先访问左子树,然后访问右子树,最后将根节点的值加入结果集中。时间复杂度为$O(n)$,空间复杂度为$O(n)$,其中$n$是二叉树的节点数。

class Solution {
   
       public List<Integer> postorderTraversal(TreeNode root) {
   
           List<Integer> result = new ArrayList<>();        if (root == null) {
   
               return result;        }        Stack<TreeNode> stack = new Stack<>();        TreeNode prev = null;        while (root != null || !stack.isEmpty()) {
   
               while (root != null) {
   
                   stack.push(root);                root = root.left;            }            root = stack.peek();            if (root.right == null || root.right == prev) {
   
                   result.add(root.val);                stack.pop();                prev = root;                root = null;            } else {
   
                   root = root.right;            }        }        return result;    }}

在这个实现中,我们使用栈来模拟递归。首先将根节点入栈,然后不断将左子树入栈,直到左子树为空。然后我们查看栈顶元素,如果右子树为空,或者右子树已经被访问过了,则将栈顶元素出栈,并将其加入结果集中。否则,我们将右子树入栈,并将其作为新的根节点,继续遍历。时间复杂度为$O(n)$,空间复杂度为$O(n)$,其中$n$是二叉树的节点数。

4、Spring IOC、AOP

Spring是一个基于Java的开源框架,提供了很多的功能和特性,其中最重要的两个特性是IOC(控制反转)和AOP(面向切面编程)。

IOC(控制反转)是一种设计模式,它将应用程序的控制权从代码中转移到了外部容器中。在Spring中,容器负责管理对象的生命周期和依赖关系,这样开发人员就不需要自己去创建和管理对象了。通过IOC,我们可以实现松耦合的应用程序,便于维护和扩展。

在Spring中,IOC的实现方式是通过依赖注入(Dependency Injection,DI)来实现的。依赖注入是指将一个对象所需要的依赖关系通过外部容器注入到该对象中。Spring提供了三种注入方式:构造函数注入、setter方法注入和字段注入。

AOP(面向切面编程)是一种编程范式,它的主要目的是分离关注点和业务逻辑。在Spring中,AOP可以实现横切关注点的管理,例如日志、事务、权限等,这些关注点可以在多个模块中重复使用,避免了代码的重复编写,提高了代码的可重用性和维护性。

在Spring中,AOP的实现方式是通过代理来实现的。Spring提供了两种代理方式:JDK动态代理和CGLIB代理。JDK动态代理是基于接口的代理,它只能为接口创建代理对象,而CGLIB代理是基于类的代理,它可以为任何类创建代理对象。在AOP中,我们需要定义切面(Aspect),切面是一个包含切点(Pointcut)、通知(Advice)和切面类型的对象。通知是在切点前后执行的代码,切点是指切面要应用的一组连接点。切面类型包括前置通知(Before)、后置通知(After)、环绕通知(Around)、返回通知(AfterReturning)和异常通知(AfterThrowing)。

综上所述,IOC和AOP是Spring中最重要的两个特性,它们分别实现了控制反转和面向切面编程的功能,让应用程序更加灵活、可重用和易于维护。

5、Docker,常用命令、主机的文件复制到容器里的命令

Docker是一种开源的容器化平台,提供了一种便捷的方法来打包、运输和运行应用程序。下面是常用的Docker命令:

docker run:启动一个容器

docker ps:列出所有正在运行的容器

docker images:列出所有镜像

docker build:构建一个新的镜像

docker stop:停止一个正在运行的容器

docker rm:删除一个容器

docker rmi:删除一个镜像

docker exec:在一个正在运行的容器中执行命令

docker logs:查看一个容器的日志

docker inspect:查看一个容器的详细信息

docker network:管理Docker网络

docker-compose:管理多个容器的组合和部署

如果需要将主机上的文件复制到容器中,可以使用以下命令:

docker cp:将主机的文件复制到容器中

例如,将主机上的文件/home/user/data.txt复制到容器container1的/data目录下,可以使用以下命令:

docker cp /home/user/data.txt container1:/data/

其中,/home/user/data.txt是主机上的文件路径,container1是容器名,/data/是容器中的目标路径。

6、讲一下 K8s

kubernetes(简称K8s)是一种开源的容器编排平台,它可以自动化地部署、扩展和管理容器化的应用程序。它提供了一种便捷的方法来管理容器,从而让开发人员和运维人员更加专注于应用程序的开发和运维,而不用关注底层的基础设施。

Kubernetes由Google开发并开源,它的目标是提供一种通用的、可移植的、可扩展的平台,用于管理容器化的应用程序。Kubernetes可以运行在多种云计算平台、物理服务器和虚拟机上,支持多种容器运行时,例如Docker、CRI-O等。

Kubernetes的核心是一个集群,它由多个节点组成,每个节点都运行一个Kubernetes Agent,负责管理节点上的容器。在集群中,有一个Master节点,负责集群的管理和控制。Master节点包括以下几个组件:

API Server:提供Kubernetes API,用于与其他组件进行通信。

etcd:分布式键值存储,用于存储Kubernetes集群的配置信息。

Controller Manager:负责监控集群中各个资源的状态,并进行调度和处理。

Scheduler:负责将Pod调度到合适的节点上运行。

在Kubernetes中,应用程序被打包成一个或多个Pod,每个Pod包含一个或多个容器。Pod是Kubernetes中最小的调度单位,它可以部署到任何一个节点上,并且可以水平扩展。每个Pod都有自己的IP地址和网络命名空间,它们之间可以通过容器网络进行通信。

除了Pod,Kubernetes还有其他一些重要的资源对象,例如Service、Volume、Namespace等。Service是用来暴露Pod的网络服务,Volume是用来管理Pod中的存储数据,Namespace是用来对Kubernetes资源进行隔离和分组。

Kubernetes提供了许多功能和特性,例如自动伸缩、负载均衡、故障转移、自动部署等。通过Kubernetes,开发人员和运维人员可以更加轻松地管理和运维容器化的应用程序,从而提高开发效率和运维效率。

7、RPC 的理解,了解 Dubbo 么

RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,它允许一个程序在不同的地址空间中调用另一个程序的子程序,就像调用本地的子程序一样。RPC通常使用客户端/服务器模型,客户端调用远程服务器上的一个函数,并返回结果。

RPC协议在分布式系统中广泛使用,它可以使分布式系统中的各个部分像本地系统一样互相调用。RPC协议的实现通常涉及序列化和反序列化、网络传输、消息路由、协议处理等技术。

Dubbo是一种基于Java的高性能RPC框架,由阿里巴巴开发并开源。Dubbo提供了一种方便的方式来实现分布式服务的调用,它支持多种协议和序列化方式,例如dubbo、http、hessian、json等,同时支持负载均衡、服务治理、动态路由、自适应调整等功能。

Dubbo的架构包括三层:服务接口层、代理层和实现层。服务接口层定义服务接口和数据模型;代理层实现客户端和服务端的远程调用;实现层提供了服务的具体实现。

Dubbo的优点在于高性能、简单易用、支持服务治理等。它在阿里巴巴集团内部广泛应用,也在开源社区得到了广泛的关注和应用。

sql,一张表,一条语句,得到成绩>=60和<60的人数,不能使用两条语句分别查询。

SELECT SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END) AS pass_count, SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS fail_count FROM your_table;

8、慢查询怎么定位具体哪的问题

慢查询是指在数据库执行查询语句时,需要消耗大量时间才能返回结果的查询操作。在定位慢查询问题时,可以采用如下步骤:

开启慢查询日志:在 MySQL 中,可以通过设置 slow_query_log 参数来开启慢查询日志。在慢查询日志中,会记录所有执行时间超过阈值的查询语句和相关信息。

分析慢查询日志:可以使用工具如 pt-query-digest、mysqldumpslow 等来分析慢查询日志,并生成报告,报告中会列出执行时间最长的查询语句和相关信息。

优化慢查询:根据分析结果,可以对慢查询语句进行优化。常用的优化方式包括增加索引、重构查询语句、分析数据表结构等。

重复上述步骤:对于经过优化后仍然存在慢查询的情况,可以重复上述步骤来定位问题。

在分析慢查询时,可以关注以下几个方面:

查询语句是否使用了索引:查询语句没有使用索引可能导致查询效率较低。

查询语句的执行计划:执行计划可以帮助分析查询语句的执行过程,找到可能存在的瓶颈。

数据表结构:数据表结构的设计可能会影响查询效率,例如表中字段类型的选择、表的范式设计等。

数据库参数的设置:数据库参数的设置可能会影响查询效率,例如 buffer_pool_size、max_connections 等参数。

通过以上的分析和优化,可以定位慢查询的问题并提高查询效率。

9、负载均衡,服务器配置(实话实说没操作过,讲了下负载均衡是怎样的)

负载均衡是一种常用的分布式系统技术,用于将请求分发到多个服务器上,以提高系统的可靠性、可用性和扩展性。在实现负载均衡时,需要考虑服务器配置的问题。

服务器配置是指服务器的硬件和软件配置,包括 CPU、内存、硬盘、操作系统、应用程序等。在负载均衡中,需要将请求均衡地分发到多台服务器上,因此需要考虑服务器配置的平衡性,以充分利用每台服务器的资源,避免资源浪费或瓶颈。

一般来说,服务器配置需要考虑以下几个方面:

CPU:服务器的 CPU 对于负载均衡非常重要,因为它直接影响系统的处理能力。在选择 CPU 时,需要考虑其主频、核心数、缓存大小等因素。

内存:服务器的内存也非常重要,因为它直接影响系统的并发处理能力。在选择内存时,需要考虑其容量和速度等因素。

硬盘:服务器的硬盘也会影响系统的性能。在选择硬盘时,需要考虑其容量、转速、接口等因素。

操作系统:服务器的操作系统也很重要,因为它直接影响系统的稳定性和安全性。在选择操作系统时,需要考虑其版本、稳定性、安全性等因素。

应用程序:服务器上的应用程序也会影响系统的性能和稳定性。在选择应用程序时,需要考虑其版本、性能、稳定性等因素。

在实现负载均衡时,需要根据具体的业务需求和系统性能要求来选择服务器的配置。需要注意的是,不同的负载均衡算法可能会对服务器配置有不同的要求,例如基于轮询的算法可能对服务器配置要求较低,而基于响应时间的算法可能对服务器配置要求较高。

10、自动化这块,Selenium的原理、PO模式的优点

Selenium是一种自动化测试工具,可以用于自动化测试Web应用程序。它主要是通过模拟用户在浏览器中的操作,来实现自动化测试。

Selenium的原理:

Selenium主要通过浏览器驱动来实现自动化测试。浏览器驱动可以模拟用户在浏览器中的操作,例如打开浏览器、输入URL、填写表单、点击按钮、滚动页面、获取元素等。在自动化测试中,开发人员可以通过编写脚本来调用浏览器驱动,以实现自动化测试。

Selenium支持多种编程语言和多种浏览器,可以在不同的平台上运行。开发人员可以通过编写脚本来调用Selenium的API,以实现自动化测试。

PO(Page Object)模式是一种常用的自动化测试模式,它的主要思想是将页面对象抽象出来,通过编写Page Object类来对页面对象进行封装和管理,以简化测试脚本的编写和维护。

PO模式的优点:

提高测试脚本的可维护性:将页面对象抽象出来,通过Page Object类来封装和管理页面对象,可以减少测试脚本的代码量,提高脚本的可维护性。

提高测试脚本的复用性:将页面对象抽象出来,可以在多个测试用例中复用相同的页面对象,提高测试脚本的复用性。

提高测试脚本的可读性:通过Page Object类来封装和管理页面对象,可以将页面对象的操作和业务逻辑分离,使测试脚本更加清晰易读。

提高测试脚本的稳定性:通过Page Object类来封装和管理页面对象,可以减少测试脚本中的错误和漏洞,提高测试脚本的稳定性。

总之,PO模式可以提高自动化测试的效率和可靠性,是一种非常实用的测试模式。

11、提到过大数据,问了 Hive,问了数据倾斜(表示没听过,就讲了下数据清洗)

Hive 是建立在 Hadoop 上的数据仓库工具,它提供了 SQL-like 的查询语言 HiveQL,使得熟悉 SQL 的开发者可以使用类 SQL 的语法来查询和处理存储在 Hadoop 分布式文件系统 HDFS 中的数据。Hive 通过将 SQL 语句转换为 MapReduce 任务来处理大规模数据集,可以用于数据分析、数据处理、数据挖掘等领域。

Hive 的特点如下:

1. 易于使用:HiveQL 语言类似于 SQL,非常容易上手。

2. 处理大规模数据:Hive 可以处理 PB 级别的数据。

3. 可扩展性:Hive 采用了 MapReduce 技术,可以方便地扩展到多台服务器上。

4. 支持多种数据格式:Hive 支持多种数据格式,包括文本、序列化、压缩等。

5. 支持自定义函数:Hive 允许用户编写自定义函数,扩展 Hive 功能。

6. 支持动态分区:Hive 支持动态分区,可以根据数据内容自动创建分区。

7. 支持数据压缩:Hive 支持数据压缩,可以减少存储空间和数据传输时间。

总之,Hive 是一款非常适合大规模数据处理的数据仓库工具,它通过 SQL-like 的查询语言 HiveQL,简化了数据处理的复杂度,同时具有良好的可扩展性和灵活性。

数据倾斜是指在分布式计算环境下,某些节点或某些键值对数据的处理时间明显大于其他节点或键值对数据的处理时间,从而导致整个计算任务的完成时间延长的现象。数据倾斜可能会导致整个分布式系统的性能下降,甚至导致任务失败。

以下是一些常见的解决数据倾斜问题的方法:

预处理数据:在进行分布式计算之前,可以对数据进行预处理,比如将数据按照某种规则划分为多个子集,从而避免出现某个节点或键值对数据的处理时间明显大于其他节点或键值对数据的处理时间。

重新分区:在某些情况下,数据倾斜是由于分区不均衡造成的。因此,可以重新分区来平衡分区的大小,从而达到均衡计算负载的目的。

Shuffle 随机化:对于一些明显倾斜的 Key,通过对这些 Key 进行一些随机化操作,将它们均匀地分布到各个节点上,从而避免某个节点过度负载的情况。

采用 Combiner 函数:Combiner 函数是一个本地聚合的操作,它可以在 Map 阶段对数据进行一些预聚合操作,从而减少 Shuffle 阶段的数据量,降低节点之间数据传输的压力,进一步减轻数据倾斜的问题。

增加节点资源:增加节点资源可以提高整个集群的计算能力,从而避免某个节点过度负载的情况,但是这种方法需要消耗大量的成本。

总之,处理数据倾斜需要根据具体情况采取不同的方法,需要对系统的运行状态进行持续监控,及时发现并解决数据倾斜的问题。

12、栈溢出的场景

栈溢出(Stack Overflow)是指程序在使用栈内存时,申请的栈空间超出了操作系统预设的栈空间大小,导致栈指针越界并发生意料之外的结果,比如程序崩溃等。下面是一些可能导致栈溢出的场景:

递归调用:如果递归调用的层数过多,栈内存就会被逐渐占满,当超出栈的容量时就会发生栈溢出错误。

局部变量过多:如果函数中定义了大量的局部变量,这些变量都会被存放在栈上,如果这些变量占用的空间过大,就有可能导致栈溢出。

函数调用深度过大:如果函数嵌套调用的层数太多,每次调用都需要占用一部分栈空间,当函数调用的深度过大时,栈就会被占满,从而导致栈溢出。

数组定义过大:如果在函数中定义了一个过大的数组,数组的空间也会被分配在栈上,这也会导致栈溢出。

指针滥用:如果指针被滥用,比如指针没有被正确初始化,或者指针越界等,这都有可能导致栈溢出。

在实际开发中,为了避免栈溢出的发生,应当尽量减少递归深度和局部变量的数量,避免过大的数组和指针越界等问题。如果出现栈溢出的情况,需要通过调整程序逻辑、减少内存占用等方法来解决。

13、什么时候触发FullGC

Full GC(Full Garbage Collection)是指对整个Java堆(包括新生代和老年代)进行垃圾回收。相比于部分回收(Partial GC),Full GC是一种相对耗时的操作,可能会导致应用程序在垃圾回收期间出现停顿。

Full GC通常发生在以下情况:

老年代空间不足:当老年代的空间被占满时,就需要进行Full GC来回收未被引用的对象,以便为新的对象腾出空间。

过多的永久代对象:如果在JVM中使用永久代来存储类和方法信息时,如果永久代对象占满了空间,就需要进行Full GC来回收未被引用的对象。

显式调用System.gc()方法:在代码中调用System.gc()方法会触发Full GC,但是并不推荐这种方式,因为它可能会导致系统的性能问题。

在实际应用中,Full GC的发生可能会导致应用程序出现停顿,因此需要对Full GC进行优化,如调整JVM参数、优化代码等。通常建议在系统低峰期进行Full GC操作,以避免对系统性能造成影响。

三面

只记得个大概。我理解三面,主要聊思想,聊宏观的,而不是很局部细节的东西。不像一、二面,问技术具体知识点。

1、项目架构

见二面面试题

2、在团队中的职责、做了哪些事情

测试开发的职责包括以下几个方面:

测试策略和计划:测试开发人员需要与测试团队和开发团队密切合作,制定测试策略和计划,包括测试范围、测试目标、测试用例设计、测试执行和测试报告等。

自动化测试开发:测试开发人员需要编写自动化测试脚本,包括单元测试、集成测试、系统测试和性能测试等,以提高测试效率和质量。此外,测试开发人员还需要选择和使用适当的自动化测试工具和框架,如Selenium、JUnit、TestNG等。

工具开发和维护:测试开发人员需要开发和维护测试工具,如测试管理工具、测试执行工具、测试数据生成工具等,以提高测试效率和质量。

缺陷管理和跟踪:测试开发人员需要协助测试团队和开发团队管理和跟踪缺陷,包括收集、分析、验证和关闭缺陷,以确保应用程序的稳定性和可靠性。

测试开发人员通常会做以下事情:

设计和编写测试用例:测试开发人员需要根据应用程序的需求和规格书设计和编写测试用例,以保证应用程序的质量和稳定性。

自动化测试脚本编写:测试开发人员需要编写自动化测试脚本,以提高测试效率和质量。

编写测试报告:测试开发人员需要编写测试报告,包括测试结果、测试覆盖率和缺陷报告等,以帮助测试团队和开发团队分析和解决问题。

测试工具开发和维护:测试开发人员需要开发和维护测试工具,以提高测试效率和质量。

缺陷管理和跟踪:测试开发人员需要协助测试团队和开发团队管理和跟踪缺陷,以确保应用程序的稳定性和可靠性。

参与需求评审和设计评审:测试开发人员需要参与需求评审和设计评审,以帮助测试团队和开发团队识别潜在的问题和风险,以及提出改进建议。

3、自动化策略

自动化测试策略是指在测试计划中定义如何选择、设计和执行自动化测试用例的过程。以下是一些常见的自动化测试策略:

选择自动化测试用例:选择自动化测试用例时,应优先考虑那些需要频繁执行、执行时间长、容易出错和需要反复测试的测试用例。

设计自动化测试用例:设计自动化测试用例时,应注意测试用例的可重复性、可维护性和可扩展性,尽量减少测试用例之间的依赖关系,以便于测试执行和结果分析。

选择自动化测试工具:选择自动化测试工具时,应根据测试需求和应用程序的特性,选择适当的测试工具和框架,如Selenium、JUnit、TestNG等。

自动化测试执行:自动化测试执行时,应根据测试用例的优先级和重要性,制定测试执行计划,并对测试执行过程进行监控和管理,以确保测试质量和效率。

自动化测试结果分析和缺陷管理:自动化测试结果分析时,应对测试结果进行分类、汇总和分析,以便于发现潜在的问题和风险。同时,应对测试缺陷进行管理和跟踪,及时发现和解决问题。

持续集成和持续交付:在应用程序的开发过程中,应将自动化测试集成到持续集成和持续交付过程中,以便及时发现和解决问题,提高软件交付的质量和效率。

定期维护自动化测试脚本:自动化测试脚本需要定期维护,以适应应用程序的变化和测试需求的变化,确保测试用例的可靠性和有效性

4、印象最深的一个Bug

给出一个例子,仅供参考。

一个印象深刻的Bug是在一个电商网站上,用户在下单后,订单信息没有被正确保存。导致了多个用户在不同的时间下单时,订单信息被混淆,造成了严重的订单错误。经过调查和分析,原因是订单保存时,数据库连接池的最大连接数设置过小,导致连接池无法承载高峰期的请求量,从而导致部分订单信息没有被正确保存。

这个Bug的教训是:在设计和实现应用程序时,应充分考虑系统的容错性和可伸缩性,避免过度依赖底层资源,并定期进行性能测试和容量规划,以确保系统的可靠性和稳定性。

HR面

没问什么刁难人的问题

1、介绍公司福利

2、为什么换工作

以下是一些常见的原因:

职业发展:员工希望在新公司中寻求更好的职业发展机会,包括更高的薪资、更好的福利、更好的晋升机会、更具有挑战性的工作等。

地理位置:员工因为个人或家庭原因,希望能够找到更接近家庭或更适合自己居住的城市或地区。

总之,别说上家公司的坏话就行。

3、目前薪资,期望薪资

总结

面试的体验都非常好,比较顺利,最后顺利拿到 offer。大厂的考察范围大多比较雷同,除了具体语言外对候选人的考察维度基本就那些,无外乎就是以下几点:

1、项目经验

我记得有一次面试 shopee,让我画架构图,后来思考了一下,考察的是测试对是否了解项目的整体,对业务架构、技术架构的理解。有的会问项目一些细节,深挖项目,这块不像技术知识点那么固定,问得比较开放,没有固定答案。

2、编程语言(Python/Java/C++/Go)

Java 会问一些技术框架,Hashmap原理,垃圾回收这些八股文,Python问一些什么装饰器之类的

3、数据库相关(八股+sql)

4、Linux相关(常用命令+shell脚本)

校招考察比较多的一些计算机基础八股,操作系统、网络之类的(问的远没有校招多)

5、测试场景题,考察测试用例设计能力

算法/编程实现(测开岗的代码部分实际上没有那么要求bug free,主要是考察你的编码规范,编程思维以及用例设计,lc hot 100 +,剑指 offer 差不多已经足够,除了这些之外,一些常用语言的工程实现也可能考到,比如说多线程,装饰器,正则,文件处理,以及一些常用库的api调用等等等等)

网上面试经历分享很多,需多思考哪些是重点会常问的,推测面试官会问哪些,以做好心理预防准备。

最难的部分属于算法,如果想进大厂,这是避不开的一道防线。不进大厂了解一下常用算法(各类排序,比如说冒泡排序)思路即可,非大厂一般不会问算法或者不会问太深,顶多只问思路,不会考察代码。

面试笔记

我也为大家整理了一套最新的软件测试系统学习教程,包括测试理论、Linux基础、MySQL基础、Web测试、接口测试、App测试、Python基础、Selenium相关、性能测试、LordRunner相关等

一、软件测试基础

软件测试的步骤是什么?
如何录制测试脚本?
应该考虑进行如何测试的测试方法
怎样估计测试工作量?
测试设计的问题
当测试过程发生错误时,有哪几种解决办法?
测试执行的问题
测试评估的目标
如何提高测试?
C/S模式的优点和缺点
B/S模式的优点和缺点
…...

二、Linux

grep和find的区别? grep 都有哪些用法?
查看IP地址?
创建和删除一个多级目录?
在当前用户家目录中查找haha.txt文件?
如何查询出tomcat的进程并杀掉这个进程,写出linux命令?
动态查看日志文件?
查看系統硬盘空间的命令?
查看当前机器listen 的所有端口?
…...

三、Python

统计python源代码文件中代码行数,去除注释,空行,进行输出?
python调用cmd并返回结果?
冒泡排序
1,2,3,4 这4个数字,能组成多少个互不相同的且无重复的三位数,都是多少?
请用 python 打印出 10000 以内的对称数(对称数特点:数字左右对称,如:1,2,11,121,1221 等)
给定一个整数 N,和一个 0-9 的数 K,要求返回 0-N 中数字 K 出现的次数
判断 101-200 之间有多少个素数,并输出所有的素数
一个输入三角形的函数,输入后输出是否能组成三角形,三角形类型,请用等价类- 划分法设计测试用例
…...

四、数据库

你用的Mysql是哪个引擎,各引擎之间有什么区别?
如何对查询命令进行优化?
数据库的优化?
Mysql数据库的操作?
优化数据库?提高数据库的性能?
什么是数据的完整性?
…...

五、抓包与网络协议

抓包工具怎么用?
如何抓取https的包?如何抓取手机的包?
请求方式有哪些?
get跟post请求的区别?http跟https的区别?
......

六、接口测试

什么是接口
如果模块请求http改为了https,测试方案应该如何制定,修改?
常用HTTP 协议调试代理I具有什么?详细说明抓取HTTPS协议的设置过程?
描述TCP/IP协议的层次结构,以及每一-层中重要协议
jmeter,一个接口的响应结果如下:
接口产生的垃圾数据如何清理
依赖第三方的接口如何处理
测试的数据你放在哪?
什么是数据驱动,如何参数化?
…...

七、接口自动化

为什么做接口自动化?
你写了多少接口自动化用例?
比如说你接口的请求参数需要加密处理的,你们用的是什么加密方式,你加密怎么处理的?
你查询出来返回结果是密文,密文你怎么测试?
......

八、UI自动化与app测试

ui 自动化怎么测试?
自动化测试环境的搭建是怎样的?
seleniun 库中用过哪些函数?
定位元素的8个方法是什么?
css 定位的方法?
adb 的作用是?
App 稳定怎么做的? Monkey怎么用p (App 稳定测试 )?
App 弱网测试怎么做的?
......

九、Pytest框架与Unittest框架

Unittest 框架有哪些组件?
Unittet st 框架如何使用?
pytest 框架如何去生成测试报告?
bytes 如何去运行多个文件或者整个目录?
pytest 框架如何去运行上次失败的测试用例?
pytest 运行用例,用例命名规则有哪些?
......

十、性能测试

你认为性能测试的目的是什么?做好性能测试的工作的关键是什么?
服务端性能分析都从哪些角度来进行?
如何理解压力测试,负裁测试以及性能测试?
如何判断是否有内存泄漏及关注的指标?
描述软件产“生内存泄露的原因以及检查方式。(可以结合- 种开发语言进行描述)
简述什么是值传递,什么是地址传递,两者区别是什么?
什么是系统瓶颈?
…...


十一、人力资源

你的测试职业发展是什么?你自认为做测试的优势在哪里?
为什么我们应该录取你?
请谈谈你个人的最大特色。
一个测试工程师应具备那些素质和技能?
为什么选择测试这行?
如果我雇用你,你能给部门带来什么贡献?
…...

整份文档一共有将近 200 页【点击文末下卡片免费领取】全部为大家展示出来肯定是不太现实的,为了不影响大家的阅读体验就只展示了部分内容,还望大家海涵,希望能帮助到您面试前的复习且找到一个好的工作,也节省大家在网上搜索资料的时间来学习!

猜你喜欢

转载自blog.csdn.net/HUA1211/article/details/130866472