南京大学编译实验实验室3自动测试脚本(南京大学编译原理教程C--irsim.pyc虚拟机小程序自动执行语言实验)文章版权属于法华寺放屁小子@博客园中班(也就是我),遵循CCBY-NC-ND4.0协议。文章地址https://www.cnblogs.com/stupi...GitHub:StupidPanther本文将贴出用于编译实验3的自动测试脚本的源码,涉及版权,本文将不提供irsim.pyc虚拟机小程序和任何官方测试样本。脚本的运行需要配置python3等环境。我相信这对每个人来说都不是问题。环境配置将在后面讨论。好的,让我们进入正题。首先明确一下,这个脚本判断测试是否正确的标准是:你的编译器编译出来的IR程序是否能产生预期的输出。本地文件结构使用脚本自动测试,本地文件结构需要组织如下:.├──auto_run_irsim.py#运行irsim.pyc相关的脚本├──run.py#自动化测试脚本,是你想要执行的Script├──irsim.pyc->/home/me/Compiler/irsim/irsim.pyc#链接到irsim.pyc的软链接├──expects#你期望的输出(即执行C--编译器输出的IR文件的预期输出)│└──doc.1.1.expect├──inputs#Testsample(C--languagewritten)│└──doc.1.1.cmm├──irs#编译测试样例得到IR文件(不需要提前创建文件夹)├──outputs#执行IR程序的实际输出(不需要提前创建文件夹)└──texts#IR程序执行对应的stdin(即需要手动输入的数据)└──doc.1.1.textrun.py和auto_run_irsim.py的代码稍后贴出。接下来将说明inputs、texts、expectations文件夹中的文件应该如何准备(即如何准备测试样本)。要准备测试样本,您需要准备输入、文本和期望文件夹。Inputs文件夹:C语言源程序不用说,C语言源程序符合实验手册的要求。需要注意的是,inputs文件夹中的文件名(不带后缀)需要与texts和expects文件夹中对应的文件名相同,如上图文件结构图所示。示例如下:doc.1.1.cmm。intmain(){inta;诠释乙;阅读(一);b=a+1;写(乙);return0;}texts文件夹:执行IR程序所需要的stdin内容(即需要手动输入的数据)如果在C语言源程序中调用了read函数,那么,当相应的IR执行时,需要手动输入数据。在这里,本应手动输入的数据被写入了texts文件夹中后缀为.text的文件中。注意:每条数据以换行符结尾,文件后缀必须是.text。下面给出一个例子:doc.1.1.text,这个例子对应上面的doc.1.1.cmm,注意数字100后面有一个换行符。100expects文件夹:执行IR程序的预期输出。该脚本会自动执行你的C编译器,并将生成的IR程序存放在irs文件夹中;之后,脚本会自动运行irsim.qyc虚拟机小程序,使用它执行刚刚生成的IR程序,并将输出写入outputs文件夹。您要做的是将预期输出写入expects文件夹中以.expect结尾的文件。注意:文件末尾没有换行符,文件后缀必须是.expect。下面给出一个例子:doc.1.1.expect,对应上面的源程序和stdin。根据源程序的语义,应该期望输出整数101。注意数字101后面没有换行符。101脚本源代码下面的脚本是用python3编写的。Scriptrun.py注:脚本只需要修改一处,第42行,详见注释。#!/usr/bin/python3#作者:stupidpanther@GitHubimporttimeimportosimportreimportsysimportauto_run_irsimESC_RED="\033[31m"ESC_GREEN="\033[32m"ESC_CYAN="\033[36m"ESC_END="\033[0m"defRunParser(可执行,input_file_full_name,ir_file_full_name,output_file_full_name):os.system(“touch”+output_file_full_name)output_text=f.read()f.close()ifoutput_text=='':return0else:return-1defmain():try:print(ESC_CYAN+"scriptrunning..."+ESC_END)start_time=time.asctime(time.localtime(time.time()))num_total_files=0num_pass_files=0#任务开始#output_dir_name="./outputs/"ir_dir_name="./irs/"input_text_dir_name="./texts/"input_dir_name="./inputs/"expect_dir_name="./expects/"executable="../cc"#PleasechangethedoublequotestoyourcompilerAbsoluteaddressorrelative相对于此文件夹的地址irsim="./irsim.pyc"output_file_suffix=".output"ir_file_suffix=".ir"input_text_suffix=".text"expect_file_suffix=".expect"#makeir/outputdirifnotos.path.exists(ir_dir_name):os.makedirs(ir_dir_name)ifnotos.path.exists(output_dir_name):os.makedirs(output_dir_name)#遍历输入文件forroot_dir,dirs,filesinos.walk(input_dir_name):forinput_file_nameinfiles:num_total_files+=1#===处理一个输入文件===file_pass=True#这个文件是passinput_file_full_name=root_dir+input_file_nameinput_file_pure_name=(re.findall(r"(.+)\.",input_file_name))[0]output_file_full_name=output_dir_name+input_file_pure_name+output_file_suffixir_file_full_name=ir_dir_name+input_file_pure_name+ir_file_suffixinput_text_file_full_name=input_text_dir_name+input_file_pure_name+input_text_suffixexpect_file_full_name=expect_dir_name+input_file_pure_name+expect_file_suffix#获取输出###======步骤I======run_rst=0compile_rst=0compile_rst=RunParser(executable,input_file_full_name,ir_file_full_name,output_file_full_name)ifcompile_rst==0:###==第二步======auto_run_irsim.RunIRSim()f=open(input_text_file_full_name)input_text=f.read()f.close()input_text_lines=input_text.split("\n")input_text_lines.remove('')run_rst=auto_run_irsim.RunTestCase(ir_file_full_name,output_file_full_name,input_text_lines)auto_run_irsim.StopIRSim()###====================ifrun_rst!=0:file_pass=Falseelse:ifcompile_rst!=0:print(input_file_full_name,"Compileerror,ignore.")#读取输出文件f=open(output_file_full_name)my_lines=f.readlines()f.close()#读取预期文件f=open(expect_file_full_name)official_lines=f.readlines()f.close#比较my_lines==official_lines:file_pass=Trueelse:file_pass=False#打印结果iffile_pass==True:num_pass_files+=1print(ESC_GREEN+"PASS"+input_file_full_name+ESC_END)else:print(ESC_RED+"FAIL"+input_file_full_name+ESC_END,file=sys.stderr)print(ESC_CYAN+">>>"+expect_file_full_name+">>>"+ESC_END)os.system("cat"+expect_file_full_name)print("")打印(ESC_CYAN+">>>"+output_file_full_name+">>>"+ESC_END)os.system("cat"+output_file_full_name)print("")##missionccompleteend_time=time.asctime(time.localtime(time.time()))print("------")print("文件总数:",num_total_files)print("通过文件数:",num_pass_files)print("-----")print(ESC_CYAN+"开始于"+start_time+ESC_END)print(ESC_CYAN+"结束于"+end_time+ESC_END)ifnum_total_files==num_pass_files:sys.exit(0)else:sys.exit(-1)exceptExceptionasexcep:print(excep,file=sys.stderr)sys.exit(-2)if__name__=="__main__":main()脚auto_run_irsim.py这个脚无需修改任何内容#!/usr/bin/python3#作者:stupidpanther@GitHubimportpyautoguiimportosimporttimeimportgigi.require_version('Wnck','3.0')fromgi.repositoryimportWnckdefRunIRSim():os.system("python./irsim.pyc&")time.sleep(0.75)defStopIRSim():pyautogui.hotkey('alt','f4')defRunTestCase(testcase_name,output_name,input_text_lines):pyautogui.hotkey('ctrl','o')时间。sleep(0.1)pyautogui.typewrite(testcase_name)pyautogui.press('enter')time.sleep(0.05)#runpyautogui.press('f5')forlineininput_text_lines:#enterinputpyautogui.typewrite(line)pyautogui.press('enter')time.sleep(0.1)#检查是否成功src=Wnck.Screen.get_default()src.force_update()window_title=src.get_active_window().get_name()src=NoneWnck.shutdown()pyautogui.press('enter')ifwindow_title!="Finish":return-1else:#scrollpyautogui.moveTo(836,533)pyautogui.dragTo(836,350)#选择pyautogui.moveTo(492,400)pyautogui.mouseDown()pyautogui.moveTo(855,626)time.sleep(1.2)pyautogui.mouseUp()pyautogui.hotkey('ctrl','c')os.system("xclip-o>"+output_name)return0脚本使用首先给脚本执行权限:chmod+x./run.pychmod+x./auto_run_irsim.pytoautomate要执行测试样例,在当前目录下执行以下命令:(注意,脚本运行过程中不要使用鼠标或键盘)/run.py在我的本地环境中,得到如下输出:scriptrunning...通过./inputs/doc.2.2.cmmPASS./inputs/doc.1.1.cmmPASS./inputs/doc.3.1.cmmPASS./inputs/doc.2.1.cmmPASS./inputs/doc.1.3.cmmPASS./inputs/doc.2.3.cmmPASS./inputs/doc.4.1.cmmPASS./inputs/doc.1.2.cmm------总文件数:8通过文件数:8------起始于ThuMay518:24:562022endatThuMay518:25:282022environmentdependencies最后可以看到,脚本中使用了pyAutoGUI等第三方包。虽然安装它们并不难,但在这里多说几句也不是什么坏事。同样,这个脚本依赖于Python3。我的本地环境是:me@ubuntu:~$uname-aLinuxubuntu4.15.0-142-generic#146~16.04.1-UbuntuSMPTueApr1309:27:15UTC2021x86_64x86_64x86_64GNU/Linuxme@ubuntu:~$python3--versionPython3.5.2me@ubuntu:~$python3-mpip--versionpip20.3.4来自/home/me/.local/lib/python3.5/site-packages/pip(python3.5)此外,该脚本还需要安装包括但不限于以下依赖:pyAutoGUI、Wnck。关于pyAutoGUI,有人不建议在Ubuntu16.04上使用,但限于实验需要,不得不让步。我确实注意到在安装pyAutoGUI时,它的某些依赖项没有安装成功;不过本着“好用就是好用”的原则,经过实践,这并不影响我实现这个自动化测试脚本。结语写这个脚本的主要目的是为了个人使用,而不是为了用户体验,所以使用起来难免有些繁琐。快乐地与我和每个人一起试验。
