软件测试第二周作业 wordcount
Github
https://github.com/minghuatang/wordcount
PSP2.1表格
PSP2.1 | PSP 阶段 | 预估耗时 (分钟) | 实际耗时 (分钟) |
---|---|---|---|
Planning | 计划 | 20 | 20 |
· Estimate | · 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 230 | 280 |
· Analysis | · 需求分析 (包括学习新技术) | 20 | 20 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
· Design | · 具体设计 | 30 | 30 |
· Coding | · 具体编码 | 120 | 150 |
· Code Review | · 代码复审 | 10 | 10 |
· Test | · 测试(自我测试,修改代码,提交修改) | 40 | 60 |
Reporting | 报告 | 30 | 30 |
· Test Report | · 测试报告 | 5 | 5 |
· Size Measurement | · 计算工作量 | 5 | 5 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 280 | 330 |
解题思路
1. 功能分析
整个程序可分为参数分析、查找输入文件、基本计数、代码计数四个部分
(1). 参数分析:解析命令行参数,将选项保存起来,之后根据选项执行相应的命令以及输出相应的结果
(2). 查找输入文件:需要支持如"*.c"这样的简单匹配符,以及当有-s选项时需要在当前目录下递归查找文件
(3). 基本计数:实现计算文件字符数、行数、单词数的功能
(4). 代码计数:实现计算文件代码行数、空行数、注释行数的功能
2. 选择编程语言
根据功能分析的结果以及"不允许使用第三方库"的要求,选择标准库功能较为强大的Python语言
程序设计实现过程
根据功能分析所划分的模块,将代码整体分割为如下几个函数:
(1). init_argparser:设定所支持的参数,返回一个argparse.ArgumentParser对象
(2). word_count:查找当前目录下所有目标文件,对每一个目标文件调用功能执行函数,并将返回结果;若-s选项被设置,则递归查找当前目录下的各个目录
(3). file_word_count:功能执行函数,为一个目标文件调用基本计数和代码计数函数,返回结果
(4). basic_cout: 实现基本计数功能
(5). advance_count:实现代码计数功能
代码说明
入口部分:
if __name__ == "__main__": parser = init_argparser() args = parser.parse_args() count = word_count(args, os.getcwd()) count_output(args, count)
初始化标准库的参数解析对象:
def init_argparser(): parser = argparse.ArgumentParser(description="word count") parser.add_argument("filename", type=str) parser.add_argument("-o", "--output", type=str, default="result.txt") parser.add_argument("-c", "--chars", action="store_true") parser.add_argument("-w", "--words", action="store_true") parser.add_argument("-l", "--lines", action="store_true") parser.add_argument("-s", "--search", action="store_true") parser.add_argument("-a", "--advance", action="store_true") parser.add_argument("-e", "--stoplist", type=str) return parser
查找目录:
def word_count(args, rootpath): count = [] fileregex = args.filename.replace("*", "\\w*") for name in os.listdir(rootpath): path = os.path.join(rootpath, name) if args.search and os.path.isdir(path): count += word_count(args, path) elif re.findall(fileregex, name): count.append(file_word_count(args, path)) return count
根据参数调用各个功能函数:
def file_word_count(args, path): fd = open(path) wc = basic_count(fd.read()) if args.stoplist: fd.seek(0) content = fd.read() stoplist = open(args.stoplist) stopchars = stoplist.read().split() for c in stopchars: wc["words"] -= len(re.findall(c, content)) stoplist.close() if args.advance: fd.seek(0) wc.update(advance_count(fd)) fd.close() name = os.path.basename(path) wc["filename"] = name return wc
基本计数的实现:
def basic_count(content): count = { "chars": len(content)-1, "words": len(re.split(r"[\s,]+", content))-1, "lines": len(content.split('\n'))-1 } return count
代码计数的实现,逐行对文件进行分析:
def advance_count(fd): codelines = blanklines = commentlines = 0 isComment = isString = False for line in fd.readlines(): line = line.strip().replace('{', '').replace( '}', '').replace(';', '') if not isComment and not line: blanklines += 1 continue if isComment: commentlines += 1 elif line.replace('/', '').replace('*', ''): codelines += 1 line = ' '+line+' ' for i in range(1, len(line)): if line[i] == '"' and line[i-1] != '\\': isString = not isString if not isString: if line[i] == '/' and line[i+1] == '/' and not isComment: if not line[:i].split(): blanklines += 1 commentlines += 1 break if line[i] == '/' and line[i+1] == '*' and not isComment: isComment = True commentlines += 1 i += 1 if line[i] == '*' and line[i+1] == '/': isComment = False i += 1 count = { "codelines": codelines, "blanklines": blanklines, "commentlines": commentlines } return count
测试设计过程
(1). 测试文件char.c:
File write,name = new File(outputPath); writename.createNe|wFile(); Buffe,redWriter out = new BufferedWrit,er(new FileWriter(writename)); out.close();
(2). 测试文件wordtest.c:
test() { File writename = new File(outputPath); writename.createNewFile(); codeLine */ BufferedWriter out = new BufferedWriter(new FileWriter(writename)); // note line out write(outputBuffer); /* noteLine /* noteLine */ /* noteLine */ /* noteLine // noteLine */ out.flush(); out.close(); } // noteLine for(){ }/* noteLine */
(4). 测试文件stoplist.txt:
for new out
(5). 测试文件codetest.c:
test() { File writename = new File(outputPath); writename.createNewFile(); codeLine */ BufferedWriter out = new BufferedWriter(new FileWriter(writename)); // note line out write(outputBuffer); /* noteLine /* noteLine */ /* noteLine */ /* noteLine // noteLine */ out.flush(); out.close(); } // noteLine for(){}/* noteLine */
(6). 测试文件夹ddd,其中有一个wordtest.c文件
(7)测试命令如下:
wordcount.exe
wordcount.exe -c char.c
wordcount.exe -w wordtest.c
wordcount.exe -l wordtest.c
wordcount.exe -a codetest.c -o testout1.txt
wordcount.exe -s -w wordtest.c
wordcount.exe -w -e stoplist.txt codetest.c
wordcount.exe -l -w -a -c codetest.c -o testout2.txt
wordcount.exe -l -w -a -c -s wordtest.c -o testout2.txt
wordcount.exe -a -w -e stoplist.txt char.c
参考文献链接
1. https://docs.python.org/3/library/argparse.html