软件测试第二周作业 wordcount

Github

https://github.com/minghuatang/wordcount

PSP2.1表格

PSP2.1PSP 阶段预估耗时 (分钟)实际耗时 (分钟)
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

 

posted @ 2018-03-20 19:30  5kbpers  阅读(250)  评论(3编辑  收藏  举报