今天整体写下杂谈,包含java基础、spring、linux、测试和移动端相关的东西
一.java基础
1.1 多态性
问题:书写http自动化case怎么表现多态性呢?
多态性表现两方面:一种编译时多态性即重载;另一种运营时多态性即重写。
重载:同一个函数名,不同长度参数或者参数类型不同。
重写:子类继承父类重写父类方法或者实现抽象方法。
我写测试case最多就是包含测试基类,case类继承基类。
1.2 String ,StringBuilder和StringBuffer的区别:
String:是只读字符串就是final修饰,所以字符串内容不能被改变。
StringBuilder/StringBuffer:跟string相反是可以被赋值改变的。二者之间能用方法均相同,区别在于:StringBuilder因为没有被synchronized修饰,所以线程上不安全,但是效率要高于StringBuffer。
1.3抽象类和接口有什么异同
抽象类:本质还是一个类,区别在于抽象类可以包含具体方法也可以包含抽象方法,既然是一个类那么也可以时候用构造器。
成员变量可以被public,private,product和默认修饰。
继承:既然是类只能被extend继承,并且是单继承。
接口:所有成员方法都是抽象。
成员变量只能被public修饰。
实现:接口可implement实现,并且可以实现多个接口。
1.4 java中为什么会有内存泄漏呢
理论上java是GC垃圾回收机制的,所以应该不存在内存泄漏。但是实际中可以会存在无用但是可达对象,这些对象是持久态不能被回收,然而这些对象可能存在无用垃圾对象。比如说链接数据库session,如果不及时close或者flush就有可能会导致内存泄漏。
1.5 静态变量和实例变量的区别
静态变量是被static修饰的变量,它只属于类并不属于实例。静态变量在内存中只会拷贝一份。
实体变量必须依存一个实例,所以需要先创建实例在访问。
1.6 什么是DAO模式
DAO数据库或者持久化机制下提供抽象接口对象,将数据库访问封装在公共API中。DAO一共包含两种模式:一种数据访问器,另一种DataObject,前者解决如何访问数据,后者解决如何用对象封装数据。
1.7 事务ACID值什么
原子性:事务中各种操作中,要做全做要么全不做,任何一项操作失败都会导致事务失败。
一致性:事务结束后系统状态一致。
隔离性:并发事务无法看到彼此中间状态。
持久性:事务完成后会被持久化,及时发生事故也可以通过日志和同步备份重建数据。
1.8 java反射
java反射在云行中,对于任何一个类都能知道类的所有属性和方法,并且可以调用任何一个方法和属性。
反射机制优点:可以动态的执行,在业务功能需要执行方法和访问属性。
缺点:对性能有影响。
java编译知道类和对象具体信息,可以直接对类进行操作,不需要反射。
如果编译不知道就需要反射。比如类名称放到xml文件汇总,属性和属性值放到xml文件
1.9 hashmap实现原理
原理:haspmap基于哈希表Map接口非同步实现,提供可选的映射操作,并允许null作为key和value。但是不保证顺序。haspmap本质上列表+链表的数据结构。首先hash(key) 的值当作为插入列表的index。再把key对应value放入链表中。所以hashmap是无序离散型的。同样的hash值会向后插入。同时haspmap是动态扩容的,当列表数据填充度到达0.75时,会动态扩容一倍并把之前列表的key重新hash。
此外haspmap不支持线程的同步(多线程同时写hashmap)。
常用方法:put(k,v);get(key);remove(key);values();keys();
1.10. StringBuiler/StringBuffer 常用方法
insert(index,value),delete(index,value),length(),reverse()
1.11 内存泄漏和内存溢出
内存泄漏:你想系统申请内存,但是使用完后不归还,最后你自己申请内存地址自己也不能访问。系统不能再次该内存分配需要的程序这就是溢出。举例栈:栈满了,再次进栈就是上溢。栈空了还退栈就是下溢。
内存溢出:向系统申请内存时无法再次申请内存就是内存溢出(OOM)。
内存泄漏最终会导致内存溢出。
1.12 多线程
两种方式:继承Thread类和实现Runnable接口。
Thread的run方法也是调用Runnable的run方法,但是区别在于,Runnable更适合多线程资源共享。
线程状态变化:创建->就绪->运行->阻塞->销毁。
阻塞经常遇到:调用sleep(),wait()方法等。进入阻塞的线程不能进入排队队列的。只有销毁才能重新进入就绪状态。
java启动最高启动jvm守护线程和垃圾回头线程。
1.13 多线程sleep()和wait()的区别:
wait()方法:当前线程会释放监视锁,其他线程可以获取锁,待wait()方法时间到了,该线程重新获取该锁并执行锁的作用域,并用notify()通知其他线程。
wait()自动退出两种情况:
- wait()等待时间到了
- 其他线程调用锁的notify方法。
sleep()方法:静态等待方法,跟锁无关,在锁的作用域中。
https://blog.youkuaiyun.com/weiweicao0429/article/details/53185999
二.Spring 相关
2.1 spring核心模块
spring core:提供ioc服务。
spring context:提供bean访问方式。
spring aop:aop服务。
spring dao:对jdbc抽象,简化数据库访问。
spring orm:orm框架
spring mvc:http层
2.2 简单说下aop
aop:面向切面,主要对那些业务无关,但是对多个对象产生影响的行为和逻辑,抽取并封装成为可用模块。被称为“切面”。
aop实现通过两种方式:静态代理代表AspectJ;动态代理代表Spring AOP;
AspectJ是静态代理增强,就是AOP框架会在编译阶段生成AOP代理,在编译阶段将AspectJ(切面)织入java字节码。
Spring AOP动态代理不会更改java字节码,每次运行中临时生成AOP对象,这个AOP对象包含目标对象全部方法。
动态代理有两种方式:JDK动态代理和CGLIB动态代理。
2.3 简单说下IOC
控制反转,就是将创建对象交给spring容器,并且容器根据xml配置文件创建和管理各个实例的关系。最直观的体现就是new新建对象。ioc让对象创建不在使用new,而是使用java反射机制,根据配置文件动态的创建对象和管理对象。
Spring Ioc创建三种方式:构造器注入,setter方法注入和根据注解注入。
2.4 BeanFactory和ApplicationContext有什么区别:
两个都可以创建bean的核心接口。ApplicationContext是BeanFactory的子接口。
核心功能:读取bean配置文件,创建bean,管理bean,实例化,控制bean的生命周期和维护bean之间的关系。
二者区别:BeanFactory采用延迟创建bean的形式,只有getBean的时候才会创建。ApplicationContext相反采用一次性加载。
2.5 bean支持几种作用域
singleton:单例模式,每个容器只有一个bean实例。
prototype:每次请求创建bean实例。
request:每次请求的时候创建bean实例,请求完成后bean会失效并且被垃圾回收。
session:跟request差不多,每个session请求创建bean,session过期之后,bean会消失。
2.6 bean注入4种形式
set()方法注入,构造器注入,静态工厂注入,实例工厂注入。
2.7 spring 自动装配
采用@autowire注解形式。在spring xml文件中有5中形式:
no:不进行自动装配,通过手工ref属性来装配。
byName:通过name属性装配。
byType:通过数据类型装配。
constructor:通过构造器进行装配。
autodetect:自动探测,有构造采用构造器,没有构造器采用bytype形式装配。
2.8 自动装配@autowire和@resource的区别
@autowire默认按照类型装配,且依赖对象必须存在。
@resource 默认按照名称状装配,找不到名称才会用类型进行装配。
2.9 bean的生命周期
- 在spring ioc的容器 找到bean的定义并实例化bean。
- 对bean进行依赖注入
- 将bean的id传递给setbeanname方法
- 将beanfactory对象给setbeanfactory方法
- bean的销毁
2.10 RPC 原理
首先RPC建立在会话层,下一层就是TPC/IP层。通过RPC可以访问其他服务器上的方法。比如说A和B两个机器,A需要调用B机器上集群方法/函数。由于不在一个内存空间,通过rpc可以解决该类问题。
优点:
- RPC隐藏底层通信(比HTTP通信更有优势)。
- 交互模式跟http相似,发起请求->获取response.
- RPC可以像调用本地函数,调用远程的函数。
RPC主要包含三部分:RPCclient,RPCserver,注册中心。
调用流程:RPC发起请求->从bean容器获取->动态代理->rpcserver监听端口->获取返回结果->组装RPC返回结果->获取返回对象->结束调用。
用到技术:
动态代理:可以使用jdk远程动态代理或者第三方框架CGLIB等
序列化:请求序列化和反序列化。
2.11 RPC和http的区别
- 传输协议:RPC基于tcp,http就是http协议
- 传输效率:rpc应用于tcp本身请求报文更小,故传输效率更高。但是http2.0跟rpc很相似了
- 性能消耗:rpc基于二进制传输,http是基于json传输所以损耗更高
- 负载均衡:rpc自带负载均衡,http需要nginx反向代理
- 服务治理:rpc能做到自动通知,不影响上游,http需要修改nginx的配置
三 数据存储
3.1 redis
redis是非关系型数据库,主要采用key-value的形式。
redis支持类型:string,hash,list和set。
redis数据持久化采用两种形式:RDB和AOF;
redis持久化表示:将存储数据从内存写入到磁盘中,防止宕机。
RDB:核心方法两个:rdbsave生成rdb磁盘文件。rdbload 从磁盘加载文件到内存中。
AOF:一般是通过job任务,两个核心方法:write写入aof文件中;save写好aof文件保存。
二者区别:
- 更新操作多的时候使用AOF
- AOF安全性优于RDB
- RDB性能优于AOF
- 两个都配置了优先加载AOF
3.1.1 redis模式
主从复制:master一直会自身复制给slave服务器。缺点在于数据会存在不一致和没有解决master写的压力。缓解master读的压力。
集群代理型:用twitter开源框架,支持redis集群代理,业务方只有操作单个redis集群读写即可。支持失败节点自动删除。
3.1.2 什么叫缓存穿透
请求访问redis不存在key 就会访问msql ,恶意请求会一直访问不存在key,造成缓存穿透。
解决方案:
1.对于查询结果为空页缓存一个值,可以设置较短时间。
2.过滤一些不存在key,把可能存在key放入bitmap中。
3.1.3 redis和es的区别
redis:
优点:写读快、数据结构简单。
缺点:不支持条件查询、放入内存注定容量不能很大。
es:
es本身不是数据库而是一个搜索引擎。
优点:高性能,搜索快,容量高
缺点:建表之后字段类型不能修改,索引必须是建表的时候初始化好,硬件资源消耗比较高。
3.2 mysql
3.2.1 delete,drop,truncate的区别?
truncate和delete只删除数据
drop删除表结构并释放空间
删除速度:drop>truncate>delete
delete 是DML语言,需要走事务,commit之后才能生效。
drop和truncate立即生效。
delete可以删除索引,truncate不可以删除索引。
四.测试相关
4.1 项目流程
需求评审->技术评审->case书写评审->测试阶段->上线阶段->线上问题跟踪。
需求评审:捋清楚需求,确定需求是否清晰。
技术评审:rd整体设计思路,修改范围等
case书写/评审:根据需求和技术文档书写case,并确定测试排期。
前端后端拆分:前端包含页面元素样式、字段校验、接口请求、页面跳转。后端包括:字段校验、处理逻辑、调用、入库。
测试数据准备,抽象接口的暴露。
测试阶段:构建环境,冒烟case是否通过,bug提交。
上线阶段:数据索引,修改数据库表/字段,更新历史数据,配置文件,服务调用和新老接口评估。大项目回滚方案。
线上问题:对于线上问题进行归纳总结。总结:内部和外部。
外部依赖对与核心功能影响。
内部bug三类:
第一类:对功能不清晰,未完成pm需求。
第二类:覆盖率不全和评估范围不准确。
第三类:mq堵塞,服务超时,sql慢查询。
4.2 如何整体保证服务质量
测试维度:冒烟case约束提测质量->case覆盖率,核心功能回归->线上bug归类和回归case的归纳。
项目维度:需求明确合理->技术设计是否合理->测试覆盖完全。
4.3 native、PC端和小程序的区别是什么?
这个题我觉得考察M页在不同容器里面有什么不同。
移动端:M页在native和小程序的mini框架中为M页提供基础能力,PC端容器就是浏览器。
兼容性:M页在不同安卓,ios版本上。PC端不同浏览器兼容。这个有点泛泛,更多M页和native提供能力,jsbridge那个端来维护桥版本。
性能:移动端更加注重CPU,耗电量,流量等。
覆盖安装:覆盖安装和升级。
打断测试:电话,短信,音乐等系统事件。
五 移动端
5.1 简单说下 浏览器发送请求到服务端返回全过程
- client发送请求->dns服务器获取对应域名的ip地址。
- 和服务tcp建立3次握手
- 发送request请求,服务解析,如果是动态语言解析。
- 返回response
- 结束握手
5.2 安卓内存泄漏
安卓内存泄漏和java一样的,本该回收的对象因为被其他引用所以没办法回收。
常见内存泄漏:
- 单例模式的内存泄漏,context生命周期大于本身context的生命周期.
- webview加载网页过多造成的内存泄漏。
- 线程使用handler造成内存卸扣,当activity已经结束了,但是仍然在加载UI。
- 链接数据session链接使用完成后没有关闭。
定位内存泄漏:使用LeakCanary框架定位内存泄漏。
5.3 小程序相关
5.3.1 简单说了小程序的mini框架
先说下了小程序框架
Index
log
log.wxml ----------->类似html页面
log.wxss ------------>页面渲染
js ------------>和接口动态交互
app.json
page ------->各个页面路径
window --------->页面{背景颜色,标题等}
网络配置--------->网络超时配置
底部tab
app.js ------->主要监控小程序生命周期
小程序生命周期:
onload :首页进入小程序加载首页函数
onshow:该页面切到前台的时候会调用
onready:页面初次渲染只会调用一次
onhide:页面消失会调用次函数
onunload:页面卸载的的时候会调用
onPullDownRefresh():下拉刷新更新函数
onReachBottom():上拉更新钩子函数
总结:小程序主要包含webview+appserver。同时小程序是数据驱动页面,需要数据有变化才能刷新页面。
https://www.cnblogs.com/changxin7/p/12334950.html
https://www.jianshu.com/p/832bec01de37
六.linux
cpu利用率:
free:查看内存使用使用情况,free -M 为单位查看内存使用情况。
top:查看内存使用率,user/total。
iostat:查看io使用情况。
df:查看磁盘利用率。
七.python
说下装饰器
装饰器主要结局面向切面编程,类似spring的AOP,主要解决通用功能,比如说接口耗时和权限等。
装饰器书写
第一种没有参数
def getlogging(func):
@functools.wraps(func)
def wapper(*args,**kwargs):
return func(*args,**kwargs);
return wapper;
参考地址:https://www.jianshu.com/p/ee82b941772a
八.如何评价测试人员kpi
1.工作内容和质量
- 需求熟悉度和质量
- 测试用例覆盖率
- 用例的执行情况
- 提交bug的质量,bug是否描述情况
- 是否可以按时交付
2.工作效率
- 用例产出率
- bug发现率
- 测试中沟通是够及时
3.素质能力
- 工作态度
- 沟通
- 认证负责
4.加分项
- 工具开发
- 工作中发现问题,解决问题能力
相关博客: