(1)你对测试的看法,有哪些测试方法?
测试就是为了保证可靠性,有白盒和黑盒测试,黑盒测试有边界法等等方法。


(2)你在做性能测试的时候是怎样进行测试的 请简单描述一下测试的流程?
答:1.准备测试的环境(网络、范围等) 2.计划 设计 方案  3.测试执行,监控 4.问题分析,调优 5. 性能报告


测试流程

一般测试流程:
1.需求分析阶段:只要就是对业务的学习,分析需求点。
2.测试计划阶段:测试组长就要根据SOW开始编写《测试计划》,其中包括人员,软件硬件资源,测试点,集成顺序,进度安排和风险识别等内容。
3.测试设计阶段:测试方案一般由对需求很熟的高资深的测试工程师设计,测试方案要求根据《SRS》上的每个需求点设计出包括需求点简介,测试思路和详细测试方法三部分的方案。《测试方案》编写完成后也需要进行评审。
4.测试方案阶段:主要是对测试用例和规程的设计。测试用例是根据《测试方案》来编写的,通过《测试方案》阶段,测试人员对整个系统需求有了详细的理解。这时开始编写用例才能保证用例的可执行和对需求的覆盖。测试用例需要包括测试项,用例级别,预置条件,操作步骤和预期结果。其中操作步骤和预期结果需要编写详细和明确。测试用例应该覆盖测试方案,而测试方案又覆盖了测试需求点,这样才能保证客户需求不遗漏。同样,测试用例也需要评审。
5.测试执行阶段:执行测试用例,及时提交有质量的Bug和测试日报,测试报告等相关文档。


(3)关于loadrunner,和抓包工具的题目

点击打开链接  LoadRunner,是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试

LOADRUNNER的主要功能:

虚拟用户
真实负载
定位性能
分析结果
重复测试



(4)PC端有哪些操作系统,如何测试PC端下的windows操作系统上的 qq.exe的安装;tcp三次握手

1 Windows系列操作系统 由微软公司生产;

2 Unix类操作系统 如SOLARIS,BSD系列(FREEBSD,openbsd,netbsd,pcbsd);

3 Linux类操作系统 如Ubuntu,Suse Linux,Fedora,等

4 Mac操作系统  由苹果公司生产(Darwin),一般安装于MAC电脑。

windows系统里网络连接测试的exe文件是什么




(5)问了下多态是怎么实现的、java跟C++的区别、问测试一支笔


实现多态的主要手段有三种:1.虚方法virtual  2.抽象方法abstract 3.接口 interface  点击打开链接

关于虚方法需要注意的几点:虚方法必须有实现部分,哪怕是空实现。
1.父类中如果有方法需要让子类重写,则可以将该方法标记为virtual
2.虚方法在父类中必须有实现,哪怕是空实现。
3.虚方法子类可以重写(override),也可以不重写。


什么是抽象类?通俗的说就是,光说不做的类,就是不能被实例化.

抽象类存在的意义:

1.抽象类不能被实例化,只能被其他类继承

2.继承抽象类的子类必须把抽象类中的所有抽象成员都重写(实现)(除非子类也是抽象类。)

3.抽象类就是为了重写→多态(代码重用)。

4.抽象类中可以有实例成员也可以有抽象成员。


虚方法和抽象方法的区别。
虚方法必须有实现,抽象方法必须没有实现
抽象方法必须在抽象类中声明,虚方法可以出现在抽象类中
抽象方法必须在子类中重写,虚方法可以被重写



什么是接口?接口就是一种规范,协议(*),约定好遵守某种规范就可以写通用的代码。
定义了一组具有各种功能的方法。(只是一种能力,没有具体实现,像抽象方法一样,“光说不做”)。

接口定义一种能力,子类继承抽象类,实现接口。接口中的成员必须不能有实现。接口中的成员不能有访问修饰符,隐式公开。接口中可以有属性、方法、索引器等,但不能有字段。接口中的所有程序必须被子类中全部实现。



接口存在的意义:多态。多态的意义:程序可扩展性。最终→节省成本,提高效率。
接口解决了类的多继承的问题
接口解决了类继承以后体积庞大的问题。
接口之间可以实现多继承

总结:接口→抽象类→父类→具体类(在定义方法参数、返回值、声明变量的时候能用抽象就不要用具体。)

能使用接口就不用抽象类,能使用抽象类就不用类,能用父类就不用子类。
避免定义“体积庞大的接口”、“多功能接口”,会造成“接口污染”。只把相关联的一组成员定义到一个接口中(尽量在接口中少定义成员)。单一职责原则,定义多个职责单一的接口(小接口)(组合使用)。



点击打开链接Java并不仅仅是C++语言的一个变种,它们在某些本质问题上有根本的不同:
  (1)Java比C++程序可靠性更高。有人曾估计每50行C++程序中至少有一个BUG.姑且不去讨论这个数字是否夸张,但是任何一个C++程序员都不得不承认C++语言在提供强大的功能的同时也提高了程序含BUG的可能性。Java语言通过改变语言的特性大大提高了程序的可靠性。
  (2)Java语言不需要程序对内存进行分配和回收。Java丢弃了C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java语言不使用指针,并提供了自动的废料收集,Examda提示: 在Java语言中,内存的分配和回收都是自动进行的,程序员无须考虑内存碎片的问题。
  (3)Java语言中没有指针的概念,引入了真正的数组。不同于C++中利用指针实现的“伪数组”,Examda,Java引入了真正的数组,同时将容易造成麻烦的指针从语言中去掉,这将有利于防止在c++程序中常见的因为数组操作越界等指针操作而对系统数据进行非法读写带来的不安全问题。
  (4)Java用接口(Interface)技术取代C++程序中的多继承性。接口与多继承有同样的功能,但是省却了多继承在实现和维护上的复杂性。
  Java和C++各有各的优势,无需争论那种语言好,哪种语言不好,能够存在就一定有它的优势,只要你决定了要学编程就扎实的学好,编程语言都是相同的,学会一种,其他的学起来就很容易了。



(6)Linux下文档中的替换问题

答用vi命令中:%s//g



(7)如何实现播放器的测试例,怎么搭建测试网络环境,怎么模拟网络丢包环境,是否熟悉cdn,是否能从海量数据中提取top50的字 符串。

点击打开链接




(8)面试过程:C/C++的基础知识,内存泄漏、栈溢出、虚函数、 vector中的迭代器等;计算机网络:三次握手 ;数据结构:快速排序;测试:黑盒测试白盒测试



内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。 C++中内存泄漏的几种情况内存泄漏


栈溢出(stack overflow)的原因及解决办法 

出现栈内存溢出的常见原因有2个:1> 函数调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈。2> 局部静态变量体积太大。

解决办法大致说来也有两种:

1> 增加栈内存的数目;增加栈内存方法如下,在vc6种依次选择Project->Setting->Link,在Category中选择output,在Reserve中输入16进制的栈内存大小如:0x10000000

2> 使用堆内存;具体实现由很多种方法可以直接把数组定义改成指针,然后动态申请内存;也可以把局部变量变成全局变量,一个偷懒的办法是直接在定义前边加个static,呵呵,直接变成静态变量(实质就是全局变量)


C++标准库vector及迭代器

1.容器的iterator类型
每种容器类型都定义了自己的迭代器类型,如vector:vector<int> ::iterator iter;变量名为iter。
2.begin和end操作
每种容器都定义了一队命名为begin和end的函数,用于返回迭代器。如果容器中有元素的话,由begin返回的元素指向第一个元素。vector<int>::iterator iter=v.begin();若v不为空,iter指向v[0]。由end返回的迭代器指向最后一个元素的下一个,不存在,若v为空,begin和end返回的相同。
*iter=0;
iter++即将迭代器向前移动一个位置,即将v[0]赋值为0,由end返回的不允许进行解操作。==和!=操作符来比较两个迭代器,若两个迭代器指向同一个元素,则它们相等,否则不想等。
迭代器使用举例:将vector中的元素全部赋值为0;
for(vector<int>::iterator iter=v.begin();iter!=v.end();iter++)
    *iter=0;




黑盒测试和白盒测试


白盒测试:是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。
黑盒测试:是通过使用整个软件或某种软件功能来严格地测试, 而并没有通过检查程序的源代码或者很清楚地了解该软件的源代码程序具体是怎样设计的。测试人员通过输入他们的数据然后看输出的结果从而了解软件怎样工作。在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求




(9)等价类划分-答位图




(10)STL数据结构相关,vector、map的底层实现,vector的扩容机制

点击打开链接

map是无序的保存元素,只是通过它提供的接口对里面的元素进行访问,底层都是采用红黑树实现。映射,相当于字典,把一个值映射成另一个值,可以创建字典。优点:查找某一个数的时间为O(logn)、遍历时采用iterator,效果不错;缺点:每次插入值的时候,都需要调整红黑树,效率有一定影响;

----------------------------------------------------------------

vector是动态数组,在堆中分配内存,元素连续存放,有保留内存,如果减少大小后,内存也不会释放;如果新值大于当前大小时才会重新分配内存。

特点:拥有一段连续的内存空间,并且起始地址不变,因此能够非常好的支持随机存取;对头部和中间进行添加删除元素操作需要移动内存;对任何元素的访问时间都是O(1);对最后元素操作最快(在后面添加删除元素最快)。

总结:
1)需要经常随机访问且不用经常对中间元素删除插入时使用vector;
2)如果元素是结构或类,最好将结构或类的指针放入vector中,这样不仅能够节省空间,而且可避免移动时构造和析构操作;
3)删除元素时采用后面的元素覆盖前面的元素的方法可以提高效率;


扩容原理概述点击打开链接
1)新增元素:Vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素;
2)对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 ;
3)初始时刻vector的capacity为0,塞入第一个元素后capacity增加为1;
4)不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容。

为什么要成倍的扩容而不是一次增加一个固定大小的容量呢?采用成倍方式扩容,可以保证常数的时间复杂度,而增加指定大小的容量只能达到O(n)的时间复杂度,因此,使用成倍的方式扩容。

为什么是以两倍的方式扩容而不是三倍四倍,或者其他方式呢?根据查阅的资料显示,考虑可能产生的堆空间浪费,成倍增长倍数不能太大,使用较为广泛的扩容方式有两种,以2倍的方式扩容,或者以1.5倍的方式扩容。
以2倍的方式扩容,导致下一次申请的内存必然大于之前分配内存的总和,导致之前分配的内存不能再被使用,所以最好倍增长因子设置为(1,2)之间。



(11) 1. select socket 2.线程同步 3. 堆排序



select函数的作用:点击打开链接

select()在SOCKET编程中还是比较重要的,可是对于初学SOCKET的人来说都不太爱用select()写程序,他们只是习惯写诸如 conncet()、accept()、recv()或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。可是使用select()就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况。如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率高)方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。

第十二章 I/O复用


第十七章 优于select的epoll



点击打开链接 关于操作系统必知必会-进程与线程
线程同步的几种方式  线程同步的方式主要有:  临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)。
1)临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问, 如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。
2)互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享。
3)信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
4)事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。



(12)比较经典的数据在栈,堆,常量池中数据是如何分配存储的。


全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较大,一般不会溢出;函数地址、函数参数、局部变量等信息存储于栈内存,VC6中栈内存默认大小为1M,对于当前日益扩大的程序规模而言,稍有不慎就可能出问题。(动态申请的内存即new出来的内存不在栈中)

内存分配及变量存储位置(堆、栈、方法区常量池、方法区静态区) 

程序运行时,有六个地方都可以保存数据:

  1、 寄存器:这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。
  2、 堆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象)。驻留于常规RAM(随机访问存储器)区域。但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些java数据要保存在堆栈里——特别是对象句柄,但java对象并不放到其中。
  3、 堆:存放用new产生的数据。一种常规用途的内存池(也在RAM区域),其中保存了java对象。和堆栈不同:“内存堆”或“堆”最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相碰的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间
  4、 静态域:存放在对象中用static定义的静态成员。这儿的“静态”是指“位于固定位置”。程序运行期间,静态存储的数据将随时等候调用。可用static关键字指出一个对象的特定元素是静态的。但java对象本身永远都不会置入静态存储空间。
  5、 常量池:存放常量。常数值通常直接置于程序代码内部。这样做是安全的。因为它们永远都不会改变,有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。
  6、 非RAM存储:硬盘等永久存储空间。若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器,而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技艺就是它们能存在于其他媒体中,一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。


(13)平衡二叉树、tcp与udp的区别、编译原理、设计模式、对象的概念、c++与c的区别、最短路径算法、快排算法、图的深度/广度遍历、最大堆、操作系统的2个进程间的通信方式等等

百度……

(14) 二分查找,最长公共子序列等

史上最全最丰富的“最长公共子序列”、“最长公共子串”问题的解法与思路