测试开发面试经验总结

还在整理ing

C++方面

C、C++的内存机制,c++和c的主要区别

参考 https://blog.csdn.net/bitboss/article/details/62884694

  • 面向过程&面向对象:
    C是面向过程的语言,而C++是面向对象的语言。
    1 面向过程是分析出 解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
    2 面向对象是把 构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为;
    3 面向对象编程的三大特点:封装、继承、多态
    封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
    继承:使用现有类的所有功能,在无需重新编写原来的类的情况下对这些功能进行扩展。**继承的过程就是从一般到特殊的过程。
    多态:将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作

  • 动态管理内存的方法:
    C使用malloc/free函数,C++除此之外还有new/delete关键字。(两者的区别是重要考点,见下一个知识点)

  • 接下来就不得不谈到C中的struct和C++的类,C++的类是C所没有的,但是C中的struct是可以在C++中正常使用的,并且C++对struct进行了进一步的扩展,使struct在C++中可以和class一样当做类使用,而唯一和class不同的地方在于struct的成员默认访问修饰符是public,而class默认的是private;

  • C++支持函数重载,而C不支持函数重载,而C++支持重载的依仗就在于C++的名字修饰与C不同,例如在C++中函数int fun(int ,int)经过名字修饰之后变为 _fun_int_int ,而C是
    _fun,一般是这样的,所以C++才会支持不同的参数调用不同的函数;
    C++中有引用,而C没有;这样就不得不提一下引用和指针的区别(文后扩展_2);

  • C和C++动态管理内存的方法不一样,C是使用malloc/free函数,而C++除此之外还有new/delete关键字;(关于malooc/free与new/delete的不同又可以说一大堆,最后的扩展_1部分列出十大区别);

  • 接下来就不得不谈到C中的struct和C++的类,C++的类是C所没有的,但是C中的struct是可以在C++中正常使用的,并且C++对struct进行了进一步的扩展,使struct在C++中可以和class一样当做类使用,而唯一和class不同的地方在于struct的成员默认访问修饰符是public,而class默认的是private;

  • C++支持函数重载,而C不支持函数重载,而C++支持重载的依仗就在于C++的名字修饰与C不同,例如在C++中函数int fun(int ,int)经过名字修饰之后变为 _fun_int_int ,而C是
    _fun,一般是这样的,所以C++才会支持不同的参数调用不同的函数;
    C++中有引用,而C没有;这样就不得不提一下引用和指针的区别(文后扩展_2);

多态的实现方法

实现多态的二种方式:覆盖和重载。

  • 重载:是指在同一个类中相同的返回类型和方法名,但是参数的个数和类型可以不同。
    虽然人眼看起来两个函数名一样,但是编译器做过修饰后,比如int_fun,str_fun,在编译期间对于编译器已经不是一样的函数,函数的地址也在编译期间即已经绑定。因此在函数调用时,是静态的。因此重载和多态无关
  • 覆盖
    当子类重新定义了父类的虚函数后,父类指针根据赋给它不同的子类指针,动态调用属于该类的函数。这样的地址绑定在编译期间无法确定,只有运行时才动态调用。
  1. 虚函数:
    https://blog.csdn.net/IOT_SHUN/article/details/79674293
    虚函数是指一个类中你希望重载的成员函数 ,当你用一个 基类指针或引用 指向一个继承类对象的时候,调用一个虚函数时, 实际调用的是继承类的版本。
    每个类用了一个虚表,每个类的对象用了一个虚指针。

  2. 虚继承:(可以解决菱形继承的问题)
    https://blog.csdn.net/tounaobun/article/details/8443228

虚函数和纯虚函数区别,集合类的区别,比如list和vector区别,map和哈希的区别,

  • C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。C++中的纯虚函数更像是“只提供申明,没有实现”,是对子类的约束,是“接口继承”。

new和malloc

  • 属性:
    new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
  • 参数:
    使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
  • 返回类型:
    new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
  • 分配失败时:
    new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
  • 自定义类型
    new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
    malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
  • 重载
    C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
  • 内存区域:
    new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

递归和动态规划的区别

参考:https://blog.csdn.net/tyhj_sf/article/details/53969072

写了一个基函数里面有个虚函数,然后写一个派生类里面也有个虚函数,然后主程序调用虚函数调用的是哪个

派生类的虚函数

class Animal// 基类
{
public:
    virtual void getWeight(){cout << "1" << endl;}
};

class Tiger:public Animal
{
public:
    virtual void getWeight(){cout << "2" << endl;}
};

int main( )
{
    Tiger g ;
    g.getWeight();
    return 0;
}
// 输出为2,即调用派生类的虚函数

内存泄漏的原因

  • 在类的构造函数和析构函数中没有匹配的调用new和delete函数
  • 在释放对象数组时在delete中没有使用方括号
    方括号是告诉编译器这个指针指向的是一个对象数组,同时也告诉编译器正确的对象地址值并调用对象的析构函数,如果没有方括号,那么这个指针就被默认为只指向一个对象,对象数组中的其他对象的析构函数就不会被调用,
  • 缺少拷贝构造函数
    当调用默认的拷贝构造函数,两个对象指向同一块内存,将其中一个释放后,另一个将变成野指针。
  • 没有将基类的析构函数定义为虚函数
    当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有正确是释放,因此造成内存泄露

堆栈区别

海量数据存储常见问题

参考 https://blog.csdn.net/paul123456789io/article/details/54945475

虚拟内存

强引用和弱引用

如何防止数组越界

C++中数组作为形参传递给函数时把数组视为指针,并没有将数组的长度信息传递给函数,因而在函数中稍有不慎就会造成数组内存的越界访问。下面有几个解决办法:

  • 显示传递数组长度:在函数定义的参数列表中加多一个表示数组大小的参数;
void func(int arr[], size_t size)
{
    for (size_t i = 0; i < size; i++)
        // operation
}
  • 显示指定数组开始和结束的位置:这种编程风格由标准库所使用的技术启发而得,常见于迭代器的使用.
vector<int>::iterator it;

void func(int *begin, int *end)
{
    for (int *pt = begin; pt != end; pt++)
        // operation
}
  • 显示添加结束的标记:在数组末尾加多一个标识元素用来检测数组的结束,常见的例子是C风格字符串,它是一种字符数组,并且以空字符null作为结束的标记
void func(char *cstr)
{
    for (int i = 0; '\0' != cstr[i]; i++)
        // operation
}
  • 通过引用传递数组如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身
void func(int (&arr)[10])
{
    for (int i = 0; i < 10; i++)
        // operation
}
 
int main()
{
    int size = 20;
    int iarray[size] = {0};
    func(iarray); // error
    return 0;
}

测试开发方面

python-paramiko

题目:给一个文件,有几行数据,第一列是用户名,第二列是用户密码,第三列是ip地址,第四列是端口。让写一个脚本,根据用户名和密码一次登录到对应ip机器上去,然后还要发送文件等一系列操作。
答:面试官提示说python语言下封装了一个库,名字忘记了,回来查了一些是 paramiko,应该没有错。具体方法:
参考:https://blog.csdn.net/songfreeman/article/details/50920767

  1. 基于用户名的sshclient方式登录,这种是传统的连接服务器、执行命令、关闭连接的操作,但是如果登录到服务器上之后还想要执行命令或者传输文件,这种方式无法实现,可以通过方法2来实现。
import paramiko
# h先建立一个sshclient对象
ssh = paramiko.SSHClient()
# h允许将信任的主机自动加入到host_all列表中,这一步必须在connet之前
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# h调用connet方法连接服务器
ssh.connet(hostname = '192.168.2.129", port = 22, username = 'super', password = 'super')
# h执行命令
stdin, stdout, stderr = ssh.exec_command('df -hl')
# h如果有结果放到stdout中,如果有错误放到stderr中
print(stdout.read().decode())
# h关闭连接
ssh.close()
  1. 基于用户名和密码的transport方式登录,这种方式
# h先实例化一个transport对象
trans = paramiko.Transport(('192,168.2.129, 22))
# h建立连接
tran.connet(username = 'super', password = 'super')
# h将sshclient对象的transport指定为上面的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# h执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# h关闭连接
trans.close()
  1. 基于公钥密钥的SSHClient登录
# h指定本地的RSA私钥文件,如果建立密钥对时设置有米娜,password为密码,不需要的时候password缺省即可;
pkey = paramiko.RSAKey.from_private_key_file('/home/super/.ssh/id_rsa', password = '12345')
# h建立连接
ssh = paramiko.SSHClient()
ssh.connet(hostname = '192.168.2.129',
					port = 22,
					username = 'super',
					pkey = pkey)
# h执行命令
stdin, stdout, stderr(exec_command('df -hl))
print(stdout.read().decode())
# h关闭连接
ssh.close()
  1. 传输文件sftp的实现
# h实例化一个trans对象
trans = paramiko.Transport(('192.168.2.190', 22))
# h建立连接
trans.connet(username = 'super', password = 'super')
# h实例化一个sftp对象,指定连接的通道
sftp = paramiko.SFTPClient.from_transport(trans)
# h发送文件
sftp.put(localpath = '/home/super/1.txt', remotepath = 'tmp/22.txt')
# h下载文件
sftp.get(remotepath, localpath)
trans.close()

一个网站的安全性测试?

题目:对于一个网站,能想到的测试用例,安全测试方面怎么考虑?
答:参考 http://www.cnblogs.com/TankXiao/p/3154017.html
首先,查找需求说明、网站设计等相关文档,分析测试需求。

  • 功能测试:等价类测试方法
  1. 输入正确的用户名和密码,点击提交按钮,验证是否可以正确登录;
  2. 提交功能的测试。
  3. 输入错误的用户名或者密码,验证登录失败,并校验错误信息的显示;
  4. 非法用户名和密码,包括长度的校验,以及非法字符或者空格等的校验;
  5. 登录成功后是否有正确的页面跳转;
  6. 记住用户名或者密码的功能
  • 界面测试:
  1. 布局是否合理,2个testbox和一个按钮是否按照要求界面显示对齐等
  2. 按钮的长度高度等校验
  • 性能测试:
    从以下三个方面考虑:
    压力测试:通过对系统不断施压,来 确定系统瓶颈或不能接受用户请求的性能点,以获得系统能提供的最大服务级别。
    负载测试:通常是让被测系统在其 能忍受的压力极限范围内(或临界状态下)连续运行,来测试系统的稳定性。
    强度测试:为了确定系统在最差工作环境的工作能力,也可能是用于验证在 标准工作压力下的各种资源的最下限指标。
    负载测试侧重于压力持续的时间,而压力测试则更加强调施加压力的大小。
    测试指标:并发量(吞吐量),延迟(最大\最小\平均)以及顺序指标等
  1. 打开登录页面需要几秒;
  2. 输入正确的用户名或者密码后,登录成功跳转到新页面的时间;
  3. 能支持多少用户同时登录;
  • 安全性测试:
  1. 登录成功后生成的 Cookie是否为httponly(否则很容易被脚本盗取)
    (cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击)

  2. 用户名和密码是否为加密 发送给Web服务器;

  3. 用户名和密码的验证应该是 服务器端验证,而不能是客户端用JavaScript验证;

  4. 用户名和密码的输入框,屏蔽SQL注入攻击
    (部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据即SQL注入。
    防御办法:
    步骤一,严格检查输入变量的类型和格式;
    步骤二,过滤和转义特殊字符;
    步骤三,利用mysql的预编译机制:把sql语句的模板(变量采用占位符进行占位)发送给mysql服务器,mysql服务器对sql语句的模板进行编译,编译之后根据语句的优化分析对相应的索引进行优化,在最终绑定参数时把相应的参数传送给mysql服务器,直接进行执行,节省了sql查询时间,以及mysql服务器的资源,达到一次编译、多次执行的目的,除此之外,还可以防止SQL注入。具体是怎样防止SQL注入的呢?实际上当将绑定的参数传到mysql服务器,mysql服务器对参数进行编译,即填充到相应的占位符的过程中,做了转义操作。

  5. 用户名和密码的输入框,应该禁止输入脚本,防止XSS攻击
    (XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。
    防御办法:
    步骤1、对所有用户提交内容进行可靠的输入验证,包括对URL、查询关键字、HTTP头、POST数据等,仅接受指定长度范围内、采用适当格式、采用所预期的字符的内容提交,对其他的一律过滤。
    步骤2、实现Session标记(session tokens)、CAPTCHA系统或者HTTP引用头检查,以防功能被第三方网站所执行。
    步骤3、确认接收的的内容被妥善的规范化,仅包含最小的、安全的Tag(没有javascript),去掉任何对远程内容的引用(尤其是样式表和javascript),使用HTTP only的cookie。)

  6. 错误登录的次数限制,防止暴力破解

  • 兼容性测试:
  1. 主流的浏览器下是否都可以显示正常以及功能正常;
  2. 不同的平台下是否都可以正常工作,windows,linux,mac
  3. 移动设备上是否都可以正常工作,Android,IOS
  4. 不同分辨率
  5. 不同的浏览器大小(浏览器的最大化和非最大化)

cookie 和session 的区别

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中

有没有涉及到单元测试?

单元测试是白盒测试,就是针仅仅针对代码来说,不涉及任何工具等等。面试官问道这个问题应该是想问白盒测试的方法。参考:
https://blog.csdn.net/write6/article/details/78702977
从语句覆盖、判定覆盖、判定条件覆盖、条件组合覆盖、路径覆盖,测试用例的覆盖强度一次增强。

  • 语句覆盖:就是 覆盖每一条执行的语句 即可。如下图,测试用例为:
    A^B = T
    在这里插入图片描述
  • 判定覆盖(分支覆盖)
    对于判断语句,涉及用例时要覆盖语句 结果为True和False的情况。测试用例为:
    A^B = T
    A^B = F
    在这里插入图片描述
  • 条件覆盖
    对于判断条件中,每一个条件表达式true和false均取值一次。
    A = T A = F
    B = T B = F
    在这里插入图片描述
  • 判定条件覆盖(分支条件覆盖)
    判断语句中 每个条件表达式的所有可能结果至少出现一次,每个判断语句本身所有可能结果也至少出现一次
    A^ B = T A^B = F
    A = T A = F
    B = T B = F
    在这里插入图片描述
  • 条件组合覆盖
    设计测试用例时,使得每个判断语句中条件结果的所有可能组合至少出现一次。
    A= T, B = T
    A = T,B = F
    A = F,B = T
    A = F,B = F
    在这里插入图片描述
  • 路径覆盖
    涉及用例时,覆盖程序中所有可能执行的路径。覆盖的比较彻底,包括循环、分支选择、条件组合等。但是缺点是使得工作量呈指数级增长。

请从不同维度设计测试点:用户使用手机app发表一篇帖子,帖子内容包含文字,图片,定位信息等多种富文本数据。

升级http协议到https协议,我们需要测试哪些东西?

  • http协议:是超文本传输协议,被用于在web浏览器和网站服务器之间传递信息。http协议工作是以明文方式发送内容,不提供任何形式的数据加密,而这也是很容易被黑客利用的地方,如果黑客截取了web浏览器和网站服务器之间的传输信息,就可以直接读懂其中的信息,因此http协议不适合传输一些重要的、敏感的信息,比如信用卡密码及支付验证码等。
  • 安全套接字层https协议就是为了解决http协议的这一安全缺陷而出生的,为了数据传输的安全,https在http的基础上加入了ssl协议,ssl依靠证书来验证服务器的身份,为浏览器和服务器之间的通信加密,这样的话即使黑客借去了发送过程中的信息,也无法破解读懂它,我们网站及用户的信息便得到了最大的安全保障。
  • HTTPS和HTTP的区别主要为以下四点:
    1、安全协议配置费用,https协议需要到ca申请证书,一般免费证书很少,需要交费;
    2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议;
    3、http和https使用的是完全不同的连接方式,用的端口不一样,前者是80,后者是443;
    4、http的连接很简单,是无状态的;https协议是由ssl+http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
    简单来说,http协议+安全套=https协议。

一串数字,闰年的判别

1、能整除4且不能整除100
2、能整除400

上网的时候界面有时候会弹出广告,你觉得是什么原因?

因为 HTTP 是明文传输的,在传输过程中,在一些路由节点中很容易被别人捕获,识别你的内容,再在传输的数据中添加一些广告代码,最后数据传到你的手机里就显示成这样了,很不爽。而 HTTPS 能很有效的解决这个现象,我们在数据传输之前,双方商量一个加密的密码,然后俩个人之间的通讯都用这个密码进行加密,即便在路由节点被第三方捕获,它没有密码,看到的也是一堆乱码,没有办法在合适的位置插入广告代码,

一个web页面操作响应过慢,如何定位原因?

做压力测试时,需要在负载机模拟大量用户,如何判断负载机本身不会成为瓶颈?

给你一个QQ群,怎样测试其中一个群成员发送消息,其他的成员都收到消息了?

qq是怎么实现在线大文件的传输的

算法编程方面

统计文本文件中出现次数前10的单词,注意文件很大,不能一次性读入内存

如何判断两个链表是否相交

比较两个json数据是否相等

判断链表是否有环

怎么求两条链表的交点

怎么求两条链表的交点

给定文件中读取QQ号,将有异常的QQ筛掉,将QQ号和次数打印出来;

洗牌算法。

找出数组第k大的元素

参考 https://www.cnblogs.com/dsj2016/p/5500204.html

  • 冒泡法:因为每次冒泡都是把当前未排序的序列中最大值冒到最后,因此冒到第k次时就是第k大的元素。复杂度是O(N*K);
  • 用快排:快排每次把一个元素放到排序后对应的坑中,

实现strcpy函数

实现字符串拼接函数

回文算法

有序单链表的反转

子串在父串的第一次出现的位置

0000到9999这1万个数中有多少个数字7(请不要理解为多少个数包含7)

提示:方式1,可以通过找规律的方式,比如1到10,1到100,1到1000分别多少个7;方式2,对每一位单独考虑,共四位,每一位出现7的概率是1/10;方式3,每次固定一位,变换其他位,比如固定千位为7,那么就有1000个,依次计算,得到最终结果4000

字符串的逆序 手写代码

二叉树先序遍历

不用循环找出数组最大值

计网方面

TCP协议和UDP协议的区别

TCP和UDP各自适用的场合

TCP协议的拥塞控制和流量控制

拥塞控制大概是指对于整个网络的拥堵情况来判断,比较全面一点。流量控制是根据接收方的窗口限制发送方的发送窗口。
慢开始:
快恢复:

TIME WAIT了解吗

TCP劫持了解吗

HTTPS协议

两个机器之间的通讯过程?(后来换了个问法是计算机网络为什么会有七层?)

项目方面

  1. 实习经历看起来是比较偏后台测试方面,怎么测试?每个服务发送消息的协议是???

linux命令行

统计一个文件中的某个单词个数以及替换

查看进程、top命令、查看磁盘

查看CPU状态

智力题

a城有3000kg的草粮,a b 两城相距1000km,一匹马每走1km就消耗1kg草粮,从a城到b城最多能运多少草粮?

开放问题

哪门课印象最深

  • 1
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值