登录页面
用户名输入框:密码输入框:
验证码输入框:
记住我复选框:
注册超链接
一、简答题(40分)
1、什么是进程,什么是线程
进程:资源分配的基本单位,它是程序执行时的一个实例,在程序运行时创建;
线程:是程序执行的最小单位,是进程的一个执行流,一个进程由多个线程组成;
2、线程的调度机制有那些
1.抢占式线程调度,每个线程可能会有自己的优先级,但是优先及并不意味着高优先级的线程一定会被调度,而是由cup随机的选择,所谓抢占式的线程调度,就是说一个线程在执行自己的任务时,虽然任务还没有执行完,但是cpu会迫使它暂停,让其它线程占有cpu的使用权。
2.协作式线程调度,每个线程可以有自己的优先级,但优先级并不意味着高优先级的线程一定会被最先调度,而是由cpu时机选择的,所谓协作式的线程调度,就是说一个线程在执行自己的任务时,不允许被中途打断,一定等当前线程将任务执行完毕后才会释放对cpu的占有,其它线程才可以抢占该cpu。
3、碎片是什么
磁盘碎片应该称为文件碎片,是因为文件被分散保存抄到整个磁盘的不同地方,而不是连续地保存在袭磁盘连续的簇中形成的。文件碎片一般不会在系统中引起问题,但文件碎片过多会使系统在读文件的时候来回寻找,引起系统性能下降,严重的还要缩短硬盘寿命。
4、同步和异步的区别
看附件
5、什么是死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
6、现在主流的内存管理是如何管理的,以及工作流程
随着 JVM 的发展,JVM 引进了分区管理的机制。 采用分区管理机制的 JVM 将 JVM 所管理的所有内存资源分为 2 个大的部分。 永久存储区(Permanent Space)和堆空间(The Heap Space)。其中堆空间又分为新生区(Young (New) generation space)和养老区(Tenure (Old) generation space),新生区又分为伊甸园(Eden space),幸存者0区(Survivor 0 space)和幸存者1区(Survivor 1 space)。具体分区如下图:
永久存储区(Permanent Space)
1)永久存储区是 JVM 的驻留内存,用于存放 JDK 自身所携带的 Class , Interface 的元数据,应用服务器允许必须的 Class,Interface 的元数据和 Java 程序运行时需要的 Class 和 Interface 的元数据。
2)被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 时,释放此区域所控制的内存。
3)如果空间不足,则会有内存溢出错误 “永久存储区溢出(java.lang.OutOfMemoryError: Java Permanent Space)”
堆空间(The Heap Space)
1)堆空间(The Heap Space)是 JAVA 对象生死存亡的地区,JAVA 对象的出生,成长,死亡都在这个区域完成。
2)堆空间又分别按 JAVA 对象的创建和年龄特征分为养老区和新生区。
3)新生区(Young (New) generation space)的作用包括 JAVA 对象的创建和从 JAVA 对象中筛选出能进入养老区的 JAVA 对象。
4)伊甸园(Eden space):JAVA 程序的所有对象在此出生,该区的名字因此而得名。也即是说当你的 JAVA 程序运行时,需要创建新的对象,JVM 将在该区为你创建一个指定的对象供程序使用。
5)创建对象的依据即是永久存储区中的元数据。
6)空间不足有JVM 堆空间溢出错误:java.lang.OutOfMemoryError: Java heap space
幸存者0区(Survivor 0 space)和幸存者1区(Survivor1 space)
1)当伊甸园的空间用完,程序又需要创建对象时,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的不再被其他对象所引用的对象进行销毁工作。同时将伊甸园中的还有其他对象引用的对象移动到幸存者0区。
2)幸存者0区就是用于存放伊甸园垃圾回收时所幸存下来的 JAVA 对象。当将伊甸园中的还有其他对象引用的对象移动到幸存者0区时,如果幸存者0区也没有空间来存放这些对象时,JVM 的垃圾回收器将对幸存者0区进行垃圾回收处理,将幸存者0区中不在有其他对象引用的 JAVA 对象进行销毁,将幸存者0区中还有其他对象引用的对象移动到幸存者1区。
3)幸存者1区的作用就是用于存放幸存者0区垃圾回收处理所幸存下来的 JAVA对象。
4)如果幸存者1区有足够空间存放则直接放到幸存者1区,如果幸存者1区没有足够空间存放,则 JVM 的垃圾回收器执行对幸存者1区的垃圾回收工作,销毁那些不再被其他对象引用的 JAVA 对象(如果该对象仅仅被一个没有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并将那些被其他对象所引用的 JAVA 对象移动到养老区。
养老区(Tenure (Old) generation space)
1)用于保存从新生区筛选出来的 JAVA 对象。
2、如果养老区有足够空间存放则直接放到养老区,如果养老区没有足够空间存放,则JVM的垃圾回收器执行对养老区区的垃圾回收工作,销毁那些不再被其他对象引用的JAVA对象(如果该对象仅仅被一个没有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并保留那些被其他对象所引用的JAVA对象。
工作运作流程:1、首先当启动 J2EE 应用服务器时,JVM 随之启动,并将 JDK 的类和接口,应用服务器运行时需要的类和接口,以及类和接口中的定义文件,还要编译后的 Class 文件或 JAR 包中的 Class 文件装载到 JVM 的永久存储区。
2、在伊甸园中创建应用服务器运行时必须的 JAVA 对象,创建 J2EE 应用启动时必须创建的JAVA对象,J2EE 应用启动完毕,可对外提供服务。 JVM 在伊甸园区根据用户的每次请求创建相应的 JAVA 对象。
3、当伊甸园的空间不足以用来创建新 JAVA 对象的时候,JVM 的垃圾回收器执行对伊甸园区的垃圾回收工作,销毁那些不再被其他对象引用的 JAVA 对象(如果该对象仅仅被一个没
有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并将那些被其他对象所引用的JAVA对象移动到幸存者0区。
4、如果幸存者0区有足够空间存放,则直接放到幸存者0区,如果幸存者0区没有足够空间存放,则 JVM 的垃圾回收器执行对幸存者 0 区的垃圾回收工作,销毁那些不再被其他对象引用的JAVA对象(如果该对象仅仅被一个没有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并将那些被其他对象所引用的 JAVA 对象移动到幸存者1区。
5、如果幸存者1区有足够空间存放则直接放到幸存者1区;如果幸存者1区没有足够空间存放,则JVM的垃圾回收器执行对幸存者1区的垃圾回收工作,销毁那些不再被其他对象引用的 JAVA 对象(如果该对象仅仅被一个没有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并将那些被其他对象所引用的 JAVA 对象移动到养老区。
6、如果养老区有足够空间存放则直接放到养老区,如果养老区没有足够空间存放,则JVM的垃圾回收器执行对养老区区的垃圾回收工作,销毁那些不再被其他对象引用的JAVA对象(如果该对象仅仅被一个没有其他对象引用的对象引用的话,此对象也被归为没有存在的必要,依此类推),并保留那些被其他对象所引用的JAVA对象。
7、如果到最后养老区,幸存者1区,幸存者0区和伊甸园区都没有空间的话,则JVM会报告 "JVM堆空间溢出(java.lang.OutOfMemoryError: Java heap space)",表示在堆空间没有空间再来创建对象。
8、这就是 JVM 的内存分区管理,相比不分区来说,一般情况下,垃圾回收的速度要快很多;因为在没有必要的时候不用扫描整片内存而节省了大量时间。 通常大家还会遇到另外一种内存溢出错误 "永久存储区溢出(java.lang.OutOfMemoryError: Java Permanent Space)"。
7、线程的几个状态以及之间的转换关系
1、new 新建状态(此时线程刚被new出来,还没执行start()方法)
2、Runable 运行状态,有执行资格又有执行权,但它可能正在等待来自操作系统的其他资源,例如处理器。
3、Blocked 阻塞状态,也称临时状态,有执行资格,但是没有执行权,需要等待执行权
4、冻结状态,有的书上又将冻结细分为Waiting 无限期等待和Timed_Waiting 有限期等待
Waiting 无限期等待状态 是用wait方法,线程自己不会醒,需要用notify方法或者其他方法来唤醒
Timed_Waiting 有限期等待状态 是用sleep方法传入一个要睡眠的时间,时间到了以后线程自己会醒
冻结状态的线程是没有执行资格,更没有执行权
5、TERMINATED 终止消亡状态:表示该线程已经执行完毕。
8、简述一下软件的生命周期
软件生命周期内有问题定义、可行性分析、总体描述、系统设计、编码、调试和测试、验收与运行、维护升级到废弃等阶段,也有将以上阶段的活动组合在内的迭代阶段,即迭代作为生命周期的阶段。
9、什么是瀑布模型
瀑布模型(Waterfall Model) 是一个项目开发架构,开发过程是通过设计一系列阶段顺序展开的,从系统需求分析开始直到产品发布和维护,每个阶段都会产生循环反馈,因此,如果有信息未被覆盖或者发现了问题,那么最好 “返回”上一个阶段并进行适当的修改,项目开发进程从一个阶段“流动”到下一个阶段,这也是瀑布模型名称的由来。包括软件工程开发、企业项目开发、产品生产以及市场销售等构造瀑布模型。
10、什么是内聚、什么是耦合,我们应该遵循怎样的规范。
11、简述OSI七层模型和TCP五层模型
12、简述一下三次握手,四次挥手https://www.cnblogs.com/Rivend/p/12028409.html
三次握手:
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
四次挥手:
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
13、写出一个HTTP的响应报文,响应数据为【hello wrold】
import socket
import _thread
import time
def send(s:socket.socket):
while True:
data=“hello wrold”
s.send(bytes(data,encoding=“utf-8”))
def recv(r: socket.socket):
while True:
b=r.recv(1024)
print("\r\n服务器发来的内容:"+str(b,encoding=“utf-8”))
cline = socket.socket()
cline.connect((“192.168.0.115”,1234))
_thread.start_new_thread(send,(cline,))
_thread.start_new_thread(recv,(cline,))
time.sleep(100)
cline.close()
14、简述一下HTTP响应码的各个含义
1xx:信息,请求收到,继续处理
2xx:成功,行为被成功地接受、理解和采纳
3xx:重定向,为了完成请求,必须进一步执行的动作
4xx:客户端错误,请求包含语法错误或者请求无法实现
5xx:服务器错误,服务器不能实现一种明显无效的请求
15、什么是黑盒测试,什么是白盒测试。
白盒测试:是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。
黑盒测试:是通过使用整个软件或某种软件功能来严格地测试, 而并没有通过检查程序的源代码或者很清楚地了解该软件的源代码程序具体是怎样设计的。测试人员通过输入他们的数据然后看输出的结回果从而了解软件怎样工作。在测试时,把程序看作一个答不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求
16、简述测试的流程
第一步:对要执行测试的产品/项目进行分析,确定测试策略,制定测试计划。该计划被审核批准后转向第二步。测试工作启动前一定要确定正确的测试策略和指导方针,这些是后期开展工作的基础。只有将本次的测试目标和要求分析清楚,才能决定测试资源的投入。
第二步:设计测试用例。设计测试用例要根据测试需求和测试策略来进行,进度压力不大时,应该设计的详细,如果进度、成本压力较大,则应该保证测试用例覆盖到关键性的测试需求。该用例被批准后转向第三步。
第三步:如果满足“启动准则”(EntryCriteria),那么执行测试。执行测试主要是搭建测试环境,执行测试用例。执行测试时要进行进度控制、项目协调等工作。
第四步:提交缺陷。这里要进行缺陷审核和验证等工作。
第五步:消除软件缺陷。通常情况下,开发经理需要审核缺陷,并进行缺陷分配。程序员修改自己负责的缺陷。在程序员修改完成后,进入到回归测试阶段。如果满足“完成准则”(ExitCriteria),那么正常结束测试。
第六步:撰写测试报告。对测试进行分析,总结本次的经验教训,在下一次的工作中改。
17、什么是Cookie?什么是session?
18、get和post有什么区别
1. Get是不安全的,因为在传输过程,数据被放在请求的URL中;Post的所有操作对用户来说都是不可见的。 2. Get传送的数据量较小,这主要是因为受URL长度限制;Post传送的数据量较大,一般被默认为不受限制。 3. Get限制Form表单的数据集的值必须为ASCII字符;而Post支持整个ISO10646字符集。 4. Get执行效率却比Post方法好。Get是form提交的默认方法。
19、在其他语言中,int类型通常占多少字节,long占多少字节,double占多少字节,folat占多数字节,char占多数字节
20、什么是位运算,b’0000 1010’<<3后的结果是多少
二、数据库(20分)
1、编写命令
创建学生表,学生包含几个字段,id、name、class、sex
创建成绩表,字段:id、studentID、courseID、score
创建课程表,字段:id、course
创建选课表,字段:id、studentID、courseID
添加四张表的主键外键
use test;
DROP table if EXISTS student;
CREATE table student
(
id int not null PRIMARY KEY ,
name varchar(20),
class varchar(20),
sex char(2)
)CHARSET=utf8;
insert into student VALUES(1,‘老王’,‘A2020’,‘男’);
insert into student VALUES(2,‘张三’,‘A2021’,‘女’);
insert into student VALUES(3,‘法外狂徒’,‘A2020’,‘男’);
DROP table if EXISTS course;
CREATE table course
(
id int not null PRIMARY KEY,
course varchar(20)
)CHARSET=utf8;
insert into course VALUES(1,‘操作系统’);
insert into course VALUES(2,‘高等数学’);
insert into course VALUES(3,‘概率论与数理统计’);
– 创建成绩表,字段:id、studentID、courseID、score
DROP table if EXISTS score;
CREATE table score
(
id int not null PRIMARY KEY auto_increment,
studentID INT not null, FOREIGN KEY(studentID) REFERENCES student(id),
courseID int not null, FOREIGN KEY(courseID) REFERENCES course(id),
score INT
)CHARSET=utf8;
insert into score VALUES(1,1,1,89);
insert into score VALUES(2,1,2,50);
insert into score VALUES(3,2,1,55);
insert into score VALUES(4,3,2,66);
insert into score VALUES(5,2,3,20);
– 创建选课表,字段:id、studentID、courseID
DROP table if EXISTS Course_selection;
CREATE table Course_selection
(
id int not null PRIMARY KEY auto_increment,
studentID INT not null,FOREIGN KEY(studentID) REFERENCES student(id),
courseID int not null,FOREIGN KEY(studentID) REFERENCES course(id)
)CHARSET=utf8;
insert into Course_selection VALUES(1,1,1);
insert into Course_selection VALUES(2,1,2);
insert into Course_selection VALUES(3,1,3);
insert into Course_selection VALUES(4,2,1);
insert into Course_selection VALUES(5,2,3);
insert into Course_selection VALUES(6,3,2);
select * from student;
select * from course;
select * from score;
select * from Course_selection;
2.1、查询所有学生的信息
2.2、查询所有学生的成绩
2.3、查询某个学生的所选的课程
2.4、查询某门课程下所有学生的成绩
2.5、查询成绩低于60,性别为难的学生信息
2.1、查询所有学生的信息
select * from student;
2.2、查询所有学生的成绩
select * from score;
2.3、查询某个学生的所选的课程
select * from student stu,Course_selection csel where stu.id = csel.studentID;
2.4、查询某门课程下所有学生的成绩
select * from course cou, student stu, score sco where sco.studentid = stu.id and sco.courseID = cou.id;
2.5、查询成绩低于60,性别为难的学生信息
select * from score sco,student stu WHERE sco.score<60 and stu.sex = ‘男’;
三、python编程(10分)
1、写出冒泡排序和选择排序算法
#冒泡排序
#1.定义一个列表zhidao
number=[6665,666,323,124,4442,5,123,412,55]
#外循环控制冒泡排序的次内数,n个数为n-1次
for i in range(0,len(number)-1):
#内循环控制每次排序对比的次数,n个数对比n-1次
for j in range(0,len(number)-1):
#进行对比,交换位容置
if(number[j]>number[j+1]):
index=number[j+1]
number[j+1]=number[j]
number[j]=index
#输出排序后的列表
print(number)
2、复制一个图片并保存
四、综合题(30分)
页面描述:
现有一个登录业务,登录页面下含如下元素,用户名输入框,密码输入框,记住我复选框,验证码输入框,登录按钮,注册超链接,验证图片。
功能描述:
用户名、密码、验证码输入框均为必选输入框
用户名长度6-24位,只允许字母开头,数字、字母、下划线组成
密码长度6-24位,允许数字、密码、下划线。
验证码长度4位
三个必选输入框输入完后,验证码正确的情况下,才允许点击登录按钮
点击验证码图片可以获得新的验证码
记住我复选框勾选后,再次访问该页面会记录上一次输入的用户名
点击超链接回自动跳转至注册页面
登录成功后,页面回跳转至个人中心
1、请根据上述页面描述,编写html页面代码。提示:验证码超链接地址(/examine)
2、根据上述功能描述,编写测试用例
看图片(有上传全手写,想哭)
3、根据题1编写自动化脚本
import unittest
import ddt
from pyUtil.webUtil import WebDriverUtil, BrowserType
@ddt.ddt
class FinalAssessment(unittest.TestCase):
def setUp(self) -> None:
print(“初始化”)
self.driver = WebDriverUtil(BrowserType.firefox, r"D:\PythonWork\Thread\pyUtil\geckodriver.exe")
self.driver.read(“xpath.json”)
def tearDown(self) -> None:
print("执行结束")
@ddt.file_data("FinalData.json")
def test_Main(self, data):
self.login(data["login"])
def login(self, login):
print("登录")
self.driver.section = "login"
self.driver.get(login["get_url"])
self.driver.find_element("username").send_keys(login["userdata"]["username"])
self.driver.find_element("password").send_keys(login["userdata"]["password"])
self.driver.find_element("code").send_keys(login["userdata"]["code"])
self.driver.find_element("submit").click()
print("登录成功!")
if name == ‘main’:
unittest.main()
4、编写接口测试代码,以及测试数据
import unittest
import requests
import ddt
import warnings
import re
@ddt.ddt
class InterfaceECShop(unittest.TestCase):
def setUp(self) -> None:
self.request = requests.session()
print(“初始化”)
def tearDown(self) -> None:
# 解决资源未关闭的问题
warnings.simplefilter("ignore", ResourceWarning)
print("结束")
@ddt.file_data("data.json")
def test_Main(self, data):
print("调用中")
self.userLogin(data["userLogin"])
# 登录
def userLogin(self, userLogin):
self.request.get(userLogin["login_path"])
respon = self.request.get(userLogin["index_path"])
print(respon.text)
assert userLogin["user_return"] in respon.text
if name == ‘main’:
unittest.main()