精华内容
下载资源
问答
  • 【人工智能项目】深度学习实现图像标签分类 本次实现一个图像标签分类的任务,接下来还会分享我研究生阶段做过的其它任务,走起瓷!!! 任务介绍 训练一个标签分类模型,使得该模型能自动根据输入的任意...

    【人工智能项目】深度学习实现图像多标签分类

    在这里插入图片描述

    本次实现一个图像多标签分类的任务,接下来还会分享我研究生阶段做过的其它任务,走起瓷!!!
    在这里插入图片描述

    任务介绍

    训练一个多标签分类模型,使得该模型能自动根据输入的任意图像提供对应图片内容的多个标签

    数据集介绍

    本次竞赛共有3.5W张图片作为训练集,8K张图片作为第一阶段评分测试集,最后6612张图片作为总决赛测试集。

    • viual_china_train.csv:图片与标签对应的列表。
    • valid_tags.txt: 6941个标签的有序列表文件。
    • tags_train.npz: 3.5W张图片对应的标签
    • train.tgz: 3.5W张训练图片
    • valid.tgz: 8K验证图片

    思路

    如猫狗大战的二分类、cifar-10的多分类,本次题目是多标签的图像分类,每张图片可能没有标签页可能存在6941个标签,即各个标签之间是不存在互斥关系的,所以最终分类的损失函数不能用softmax而必须要用sigmoid。然后把分类层预测6941个神经元,每个神经元用sigmoid函数返回是否存在某个标签即可。

    具体流程

    # 导入模块
    import os
    
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    from PIL import Image
    
    # 存放地址
    dir_path = "D:\\01\\01contest"
    print(os.listdir(dir_path))
    

    [‘tag_train.npz’, ‘train’, ‘train.tar’, ‘train.tgz’, ‘valid’, ‘valid.tar’, ‘valid.tgz’, ‘valid_tags.txt’, ‘visual_china_train.csv’]

    获取数据和标签

    先导入train_csv的数据,保存文件名以及标签名。

    # 查看数据
    train_path = os.path.join(dir_path,"visual_china_train.csv")
    train_df = pd.read_csv(train_path)
    train_df.head()
    

    在这里插入图片描述

    print(train_df.shape)
    

    (35000, 2)

    处理图片名称,将其保存到img_paths列表中

    img_paths = list(train_df["img_path"])
    

    验证图片标签是否的确只有6941个标签。

    tags = []
    for i in range(train_df["tags"].shape[0]):
        for tag in train_df["tags"].iloc[i].split(","):
            tags.append(tag)
            
    tags = set(tags)
    print("the length of tags:",len(tags))
    

    the length of tags: 6941

    前期准备工作差不多做完了,开始导入训练集。原始训练集中存在CMYK格式的图片,传统图片处理一般格式为RGB格式,所以我们使用Image库中的convert函数对非RGB格式的图片进行转换。

    # 尝试少量数据验证模型
    num_train = 5000
    X_train = np.zeros((num_train,224,224,3),dtype=np.uint8)
    i = 0
    for img_path in img_paths[:num_train]:
        img = Image.open(dir_path + "/train/" + img_path)
        if img.mode!="RGB":
            img = img.convert("RGB")
        img = img.resize((224,224))
        arr = np.asarray(img)
        X_train[i,:,:,:] = arr
        i += 1
    

    训练集导入完成,查看一下图片的样子.

    fig,axes = plt.subplots(6,6,figsize=(20,20))
    
    j = 0
    for i,img in enumerate(X_train[:36]):
        axes[i//6,j%6].imshow(img)
        j+=1
    

    在这里插入图片描述
    准备标签

    y_train_path = os.path.join(dir_path,"tag_train.npz")
    y_train = np.load(y_train_path)
    
    y_train.files
    

    [‘tag_train’]

    y_train = y_train["tag_train"]
    y_train.shape
    

    (35000, 6941)

    这样,数据和标签都拿到了,这里还是要是要分割一下数据集的。

    分割数据集用作不同用途。

    from sklearn.model_selection import train_test_split
    X_train2,X_val,y_train2,y_val = train_test_split(X_train,y_train[:num_train],test_size=0.2,random_state=2019)
    
    print(X_train2.shape)
    print(y_train2.shape)
    print(X_val.shape)
    print(y_val.shape)
    

    (4000, 224, 224, 3)
    (4000, 6941)
    (1000, 224, 224, 3)
    (1000, 6941)

    模型搭建

    这里直接迁移模型,用ResNet模型进行迁移。

    # 导入开发需要的库
    from keras.models import *
    from keras.layers import *
    from keras.optimizers import *
    from keras.callbacks import *
    from keras.applications import *
    
    base_model = ResNet50(input_tensor=Input((224,224,3)),weights="imagenet",include_top=False)
    
    for layers in base_model.layers:
        layers.trainable = False
    x = GlobalAveragePooling2D()(base_model.output)
    x = Dropout(0.25)(x)
    x = Dense(6941,activation="sigmoid")(x)
    model = Model(base_model.input,x)
    

    监测精准率 召回率 和F1的功能函数

    import keras.backend as K
    
    def precision(y_true, y_pred):
        # Calculates the precision
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        return precision
    
    def recall(y_true, y_pred):
        # Calculates the recall
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall = true_positives / (possible_positives + K.epsilon())
        return recall
    
    def fbeta_score(y_true, y_pred, beta=1):
        # Calculates the F score, the weighted harmonic mean of precision and recall.
        if beta < 0:
            raise ValueError('The lowest choosable beta is zero (only precision).')
        
        # If there are no true positives, fix the F score at 0 like sklearn.
        if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
            return 0
    
        p = precision(y_true, y_pred)
        r = recall(y_true, y_pred)
        bb = beta ** 2
        fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
        return fbeta_score
    
    def fmeasure(y_true, y_pred):
        # Calculates the f-measure, the harmonic mean of precision and recall.
        return fbeta_score(y_true, y_pred, beta=1)
    
    

    数据增强操作

    from keras.preprocessing.image import ImageDataGenerator
    
    train_datagen = ImageDataGenerator(width_shift_range=0.1,
                                       height_shift_range=0.1,
                                       zoom_range=0.1)
    val_datagen = ImageDataGenerator() # 验证集不做图片增强
    
    batch_size = 4
    
    train_generator = train_datagen.flow(X_train2,y_train2,batch_size=batch_size,shuffle=False)
    val_generator = val_datagen.flow(X_val,y_val,batch_size=batch_size,shuffle=False)
    

    模型训练

    keras.callbacks.ModelCheckpoint(filepath,monitor='val_loss',verbose=0,save_best_only=False, save_weights_only=False, mode='auto', period=1)

    • filename:字符串,保存模型的路径(可以将模型的准确率和损失等写到路径中,格式如下:)
    • monitor:需要检测的值如测试集损失或者训练集损失等
    • save_best_only:当设置为True时,监测值有改进时才会保存当前的模型
    • verbose:信息展示模式,0或1(当为1时会有如下矩形框的信息提示)
    • mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当监测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
    • save_weights_only:若设置为True,则只保存模型权重,否则将保存整个模型
    • period:CheckPoint之间的间隔的epoch数

    keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', epsilon=0.0001, cooldown=0, min_lr=0)

    • 当评价指标不在提升时,减少学习率
    • monitor:被监测的量
    • factor:每次减少学习率的因子,学习率将以lr = lr*factor的形式被减少
    • patience:当patience个epoch过去而模型性能不提升时,学习率减少的动作会被触发
    • mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值触发学习率减少。在max模式下,当检测值不再上升则触发学习率减少。
    • epsilon:阈值,用来确定是否进入检测值的“平原区”
    • cooldown:学习率减少后,会经过cooldown个epoch才重新进行正常操作
    • min_lr:学习率的下限
    checkpointer = ModelCheckpoint(filepath='weights_best_simple_model.hdf5', 
                                monitor='val_fmeasure',verbose=1, save_best_only=True, mode='max')
    reduce = ReduceLROnPlateau(monitor='val_fmeasure',factor=0.5,patience=2,verbose=1,min_delta=1e-4,mode='max')
    
    model.compile(optimizer = 'adam',
               loss='binary_crossentropy',
               metrics=['accuracy',fmeasure,recall,precision])
    
    epochs = 5
    
    history = model.fit_generator(train_generator,
                                 validation_data=val_generator,
                                 steps_per_epoch=num_train/batch_size,
                                 validation_steps = num_train/batch_size,
                                 epochs=epochs,
                                 callbacks=[checkpointer,reduce],
                                 verbose=1)
    

    在这里插入图片描述
    以上就是5000张图片的简单模型训练过程。

    模型保存

    model.save("model.h5")
    

    模型预测

    predict_path = os.path.join(dir_path,"valid")
    predict_img_paths = os.listdir(predict_path)
    predict_num = len(predict_img_paths)
    print(predict_num)
    

    导入测试集

    model.load_weights("weights_best_simple_model.hdf5")
    
    X_test = np.zeros((predict_num,224,224,3),dtype=np.uint8)
    i = 0
    for img_path in predict_img_paths:
        img = Image.open(predict_path + "\\" + img_path)
        if img.mode!="RGB":
            img = img.convert("RGB")
        img = img.resize((224,224))
        arr = np.asarray(img)
        X_test[i,:,:,:] = arr
        i += 1
    

    预测测试集并将结果转为中文标签,以便生成提交文件。

    y_pred = model.predict(X_test)
    
    print(y_pred.shape)
    y_pred[0]
    

    (8000, 6941)
    array([3.2395124e-05, 0.0000000e+00, 2.0861626e-07, …, 0.0000000e+00,
    0.0000000e+00, 0.0000000e+00], dtype=float32)

    # 将预测结果转换为中文标签
    
    # 第一步  形成索引和标签的字典 
    def hash_tag(filepath):
        f = open(filepath,"r",encoding="utf-8")
        hash_tag = {}
        i = 0
        for line in f.readlines():
            line = line.strip()
            hash_tag[i] = line
            i += 1
        return hash_tag
    filepath = os.path.join(dir_path,"valid_tags.txt")
    hash_tag = hash_tag(filepath)
    
    # 第二步将结果转为中文标签
    def arr2tag(arr):
        tags = []
        for i in range(arr.shape[0]):
            tag = []
            index = np.where(arr[i]>0.5)
            index = index[0].tolist()
            tag = [hash_tag[j] for j in index]
            tags.append(tag)
        return tags
    y_tags = arr2tag(y_pred)
    
    print(y_tags[0])
    

    [‘20多岁’, ‘一个人’, ‘不看镜头’, ‘东亚’, ‘东方人’, ‘亚洲’, ‘亚洲人’, ‘亚洲人和印度人’, ‘人’, ‘仅成年人’, ‘休闲活动’, ‘休闲装’, ‘女性’, ‘幸福’, ‘彩色图片’, ‘微笑’, ‘成年人’, ‘户外’, ‘拿着’, ‘摄影’, ‘放松’, ‘水平画幅’, ‘爱’, ‘生活方式’, ‘男人’, ‘男性’, ‘白昼’, ‘衣服’, ‘青年人’]

    print(len(y_tags[0]))
    print(len(y_tags[1]))
    
    29
    30
    

    生成提交文件*

    import pandas as pd
    
    df = pd.DataFrame({"img_path":predict_img_paths, "tags":y_tags})
    for i in range(df["tags"].shape[0]):
        df["tags"].iloc[i] = ",".join(str(e) for e in  df["tags"].iloc[i])
    df.to_csv("submit.csv",index=None)
    
    # 预览一下结果文件
    predict_df = pd.read_csv("submit.csv")
    predict_df.head()
    

    在这里插入图片描述

    小结

    那本次就到此为止,有问题请留言了,要是时间长了,可能也就回忆不起来了~~

    在这里插入图片描述

    展开全文
  • 最近做了一系列的单元测试相关的工作,除了各种规范及测试框架以外,讨论比较的就是关于代码覆盖的产生,c/c++与其他的一些高级语言或者脚本语言相比较而言,例如 Java、.Net和php/python/perl/shell等,由于...

    最近做了一系列的单元测试相关的工作,除了各种规范及测试框架以外,讨论比较多的就是关于代码覆盖率的产生,c/c++与其他的一些高级语言或者脚本语言相比较而言,例如 Java、.Net和php/python/perl/shell等,由于没有这些高级语言和脚本语言的反射的特性,其代码覆盖率的产生过程会稍微复杂一些。发现许多同学对C++的覆盖率如何产生在都不太清楚,这里做一个简单的介绍。

    一、基本使用方法

    在Linux上的c/c++开发一般都使用gcc/g++作为主要的编译器,如果需要产生覆盖率数据需要在Makefile或者Scons文件中做下面的编译链接设置,

    编译的时候,增加 -fprofile-arcs -ftest-coverage 或者 –coverage;

    链接的时候,增加 -fprofile-arcs 或者 –lgcov;

    打开–g3 选项,去掉-O2以上级别的代码优化选项;否则编译器会对代码做一些优化,例如行合并,从而影响行覆盖率结果;

    基本要求就上面三点,但有一个建议,为了上述几个编译选项的使用不影响到正常的编译过程(否则会极大地影响程序的运行效率)。在使用makefile中通过参数传递来支持覆盖率产生,可以在makefile使用下面的方式,

    ifeq ($(coverage), yes)

    CXXFLAGS += -fprofile-arcs -ftest-coverage

    LINKERCXX += -fprofile-arcs -ftest-coverage

    OPT_FLAGS = -g3

    endif

    这样,可以使用 make coverage=yes 来引入这些编译选项而不会影响到正常的编译(scons同理)。

    二、简单示例

    这里写了一个简单的程序做测试,主要包含三个文件:Rectangle.cpp, RectangleTest.cpp, Makefile。

    1)Rectangle.cpp 是被测代码,里面定义了一个简单的类Rectangle(长方形),里面有三个方法:

    set_values(),设置长方形对象的长和宽;

    area(),求长方形的面积;

    lenth(),求长放形的周长;

    2)RectangleTest.cpp 是一个简单的测试程序,为了demo使用,并没有使用cppunit/gtest这样的单元测试框架,直接使用了main()函数来调用Rectangle里面的方法;

    Rectangle.cpp和RectangleTest.cpp的代码如下图,

    e8e91724c7b14280e95aa01de020e9a5.png

    3)Makefile比较简单,主要支持在coverage=yes的参数支持。 可以使用-fprofile-arcs -ftest-coverage 选项,这里为了简化使用了 –coverage。

    afdf393b9e0f9d4b8a3497731a934ef2.png

    覆盖率产生的过程如下面四个步骤所示,其中步骤3和4,根据需要使用其中一种即可。

    1. 编译链接带覆盖率参数的源代码;

    2. 运行测试程序;

    3. 使用gcov获取文本形式的覆盖率数据;

    4. 使用lcov获取html形式的覆盖率数据;

    下面针对本例,做这一过程的逐步演示。

    1. 编译链接带覆盖率参数的源代码;

    由于Makeifle中已经支持了coverage=yes选项,直接运行 “make coverage=yes”,这个时候会产生测试程序,并同时生成gcno文件(关于gcno文件的详细解释,参见第三部分背后原理),如下图,

    f6bc4acffe4293dab32a62160458c42f.png

    2. 运行测试程序;

    运行./RectangleTest 测试程序,运行结束后,会针对所有的cpp源代码文件产生相应的*.gcda文件(关于gcda文件的详细解释,参见第三部分背后原理),如下图

    15a0af7bb01c39a8acda4feaf1f340a9.png

    3. 使用gcov获取文本形式的覆盖率数据;

    需要注意的是,这个步骤不是必须的,如果需要文本格式(*.gcov)的覆盖率结果,可是走这个步骤。如果想看html格式的结果,直接跳过这一步骤。gcov是gcc自带的覆盖率结果产生工具,无需单独安装。

    针对某个源代码文件,例如 Rectangle.cpp,执行”gcov Rectangle.cpp” 会产生Rectangle.cpp.gcov文件。

    be2006514830698ae7dba4e1d564d2f5.png

    这是一个存文本文件,可以通过vim打开,看到详细的行覆盖率数据,如下

    bbaf153d72594c6336ace9cdf134d7fb.png

    4. 使用lcov获取html形式的覆盖率数据;

    有些时候需要使用html结果的数据展示,这样看起来更加直观一些。IBM开源了lcov这个工具,更多参见 http://ltp.sourceforge.net/coverage/lcov.php

    工具使用,如下图,

    754e05741f6934e4baf05f0b3e2d63e9.png

    手动把cc_result目录拷贝到http/apache等服务器的htdocs目录下,可以通过浏览器来查看覆盖率结果,如下,

    707564792cce13de3b462dfca41121b1.png

    整个覆盖率生成的流程按照上面四个步骤就可以搞定。下面一节对其原理做简单的阐述。

    三、基本原理

    1. 术语解释

    在了解背后原理之前,需要对覆盖率技术的一些概念有简单的了解。主要是基本块(Basic Block),基本块图(Basic Block Graph),行覆盖率(line coverage), 分支覆盖率(branch coverage)等。

    基本块(Basic Block),”A basic block is a sequence of instructions with only entry and only one exit. If any one of the instructions are executed, they will all be executed, and in sequence from first to last.” 这里可以把基本块看成一行整体的代码,基本块内的代码是线性的,要不全部运行,要不都不运行;

    基本块图(Basic Block Graph),基本块的最后一条语句一般都要跳转,否则后面一条语句也会被计算为基本块的一部分。 如果跳转语句是有条件的,就产生了一个分支(arc),该基本块就有两个基本块作为目的地。如果把每个基本块当作一个节点,那么一个函数中的所有基本块就构成了一个有向图,称之为基本块图(Basic Block Graph)。且只要知道图中部分BB或arc的执行次数就可以推算出所有的BB和所有的arc的执行次数;

    打桩,意思是在有效的基本块之间增加计数器,计算该基本块被运行的次数;打桩的位置都是在基本块图的有效边上;

    行覆盖率(line coverage),源代码有效行数与被执行的代码行的比率;

    分支覆盖率(branch coverage),有判定语句的地方都会出现2个分支,整个程序经过的分支与所有分支的比率是分支覆盖率。注意,与条件覆盖率(condition coverage)有细微差别,条件覆盖率在判定语句的组合上有更细的划分。

    2. gcc/g++ 编译选项

    gcc需要静态注入目标程序编译选项,在编译链接的时候加入2个选项(-ftest-coverage -fprofile-arcs ),编译结束之后会生成 *.gcno 文件,而经过静态注入的目标程序在“正常结束”后,会在运行目录下产生*.gcda数据文件,通过gcov工具就可产生覆盖率数据结果。

    -ftest-coverage

    Produce a notes file that the gcov code-coverage utility (see gcov—a Test Coverage Program) can use to show program coverage. Each source file’s note file is called auxname.gcno. Refer to the -fprofile-arcs option above for a description of auxname and instructions on how to generate test coverage data. Coverage data matches the source files more closely if you do not optimize.

    让编译器生成与源代码同名的.gcno文件(note file),这种文件含有重建基本块依赖图和将源代码关联至基本块的必要信息;

    -fprofile-arcs

    Add code so that program flow arcs are instrumented. During execution the program records how many times each branch and call is executed and how many times it is taken or returns. When the compiled program exits it saves this data to a file called auxname.gcda for each source file. The data may be used for profile-directed optimizations (-fbranch-probabilities), or for test coverage analysis (-ftest-coverage). Each object file’s auxname is generated from the name of the output file, if explicitly specified and it is not the final executable, otherwise it is the basename of the source file. In both cases any suffix is removed (e.g. foo.gcda for input file dir/foo.c, ordir/foo.gcda for output file specified as -o dir/foo.o). See Cross-profiling.

    让编译器静态注入对每个源代码行关联的计数器进行操作的代码,并在链接阶段链入经态度libgcov.a,其中包含在程序正常结束时生成*.gcda文件的逻辑;

    下面通过源码解析来说明到底这2个选项做了什么。通过g++ -S选项,产生汇编语言Rectangle.s 和 Rectangle_cc.s (增加–coverage选项),命令如下,

    g++ -c -o Rectangle.s Rectangle.cpp -g -Wall -S

    g++ -c -o Rectangle_cc.s Rectangle.cpp -g -Wall –coverage -S

    vimdiff Rectangle.s 和 Rectangle_cc.s,如下图

    f89cac98e37d63f121a5cd8556d47136.png

    通过这样汇编语言的对比,可以看出gcc通过这2个参数,把打桩的过程完成了。

    更深入的内容,例如,如果想知道gcno/gcda文件的格式,可以参考 @livelylittlefish 的一篇文章,GCC Coverage代码分析-.gcda/.gcno文件及其格式分析(http://blog.csdn.net/livelylittlefish/article/details/6448885)。

    四、扩展话题

    通过上面三部分的介绍,相信绝大多数覆盖率问题都可以解决,下面2个问题是我们在实际运行过程中遇到的,也分享一下。

    覆盖率的结果只有被测试到的文件会被显示,并非所有被编译的代码都被作为覆盖率的分母

    实际上,可以看到整个覆盖率的产生的过程是4个步骤的流程,一般都通过外围脚本,或者makefile/shell/python来把整个过程自动化。2个思路去解决这个问题,都是通过外围的伪装。第一个,就是修改lcov的 app.info ,中间文件,找到其他的文件与覆盖率信息的地方,结合makefile,把所有被编译过的源程序检查是否存于 app.info 中,如果没有,增加进去。第二个伪装,是伪装 *.gcda,没有一些源码覆盖率信息的原因就是该文件没有被调用到,没有响应的gcda文件产生。toast(http://toast.taobao.org/)是通过第一种伪装来实现的,更多了解需要去看下开源代码。

    2. 后台进程的覆盖率数据收集;

    其实上述覆盖率信息的产生,不仅可以针对单元测试,对于功能测试同样适用。但功能测试,一般linux下c/c++都是实现了某个Daemon进程,而覆盖率产生的条件是程序需要正常退出,即用户代码调用 exit 正常结束时,gcov_exit 函数才得到调用,其继续调用 __gcov_flush 函数输出统计数据到 *.gcda 文件中。同样2个思路可以解决这个问题,

    第一,给被测程序增加一个 signal handler,拦截 SIGHUP、SIGINT、SIGQUIT、SIGTERM 等常见强制退出信号,并在 signal handler 中主动调用 exit 或 __gcov_flush 函数输出统计结果。但这个需要修改被测程序。这个也是我们之前的通用做法。但参加过清无同学的一个讲座后,发现了下面第二种更好的方法。

    第二,借用动态库预加载技术和 gcc 扩展的 constructor 属性,我们可以将 signalhandler 和其注册过程都封装到一个独立的动态库中,并在预加载动态库时实现信号拦截注册。这样,就可以简单地通过如下命令行来实现异常退出时的统计结果输出了。

    a1f614c7f4679e3a79e44325eddc9dcf.png

    五、其他编程语言

    展开全文
  • 但是是进行单元测试的代码覆盖统计,且测试人无法很便捷的触发和配置覆盖统计的执行,也无法直观的查看和统计覆盖统计的历史情况。亟需为测试人员提供一个简单配置就可以进行代码覆盖...

    6f4f14ff63663e06df043ccea80ebb5a.gif

    本发明属于互联网领域,尤其涉及一种Java(一种面向对象编程语言)代码覆盖率统计系统。

    背景技术:

    目前Java代码覆盖率统计解决方案要么是嵌入Ant,Maven等构件工具进行,要么是与jenkins等持续集成工具整合进行。但是多是进行单元测试的代码覆盖率统计,且测试人无法很便捷的触发和配置覆盖率统计的执行,也无法直观的查看和统计覆盖率统计的历史情况。亟需为测试人员提供一个简单配置就可以进行代码覆盖率统计,查看覆盖率统计结果的测试方案。

    技术实现要素:

    本发明针对上述技术问题,提供一种Java代码覆盖率统计系统。

    本发明是通过以下技术方案解决上述技术问题的:

    一种Java代码覆盖率统计系统,包括:

    覆盖率统计服务客户端,是被安装被测应用所在服务器上的Web(互联网总称)服务,用于:启停被测应用所在Web容器、加载或卸载Jacoco(覆盖率统计工具)相应的启动参数到Web容器的启动文件中、下载Jacoco产生的覆盖率统计文件中的至少一种;

    覆盖率统计服务端,用于:

    覆盖率统计配置,具体包括忽略模块配置、覆盖率包含配置、覆盖率排除配置中的至少一种;

    系统覆盖率统计,具体包括:通过所述覆盖率统计服务客户端在被测应用的启动过程中把Jacoco插桩到被测应用的JVM(Java虚拟机)进程中,以捕获应用过程中产生的第一覆盖率数据,通过所述第一覆盖率数据进行系统级别的覆盖率统计;

    单元测试覆盖率统计,具体包括:从Git服务器拉取单元测试用例代码到本地服务器,通过执行Jacoco-maven-plugin插件获取单元测试的第二覆盖率数据,将所述第二覆盖率数据交由SonarQube(一种代码质量管理平台)进行单元测试的覆盖率统计;

    支持所述覆盖率统计服务客户端查询覆盖率统计结果。

    较佳地,所述覆盖率统计服务端还用于:

    代码质量静态检查,具体包括从Git服务器拉取代码到本地服务器,通过执行sonar-maven-plugin插件把代码交由SonarQube进行代码静态扫描。

    较佳地,所述覆盖率统计服务端还用于:

    增量覆盖率统计,具体包括比对两个版本中新增代码的覆盖率。

    较佳地,所述覆盖率统计服务端还用于:

    一键覆盖率统计,具体包括在开启覆盖率统计后,调用配置的API(应用程序编程接口)或UI(用户界面)自动化测试平台的接口执行自动化测试平台中配置的测试用例,获取所述自动化测试平台执行完毕后的反馈结果,通过所述覆盖率统计服务客户端拉取覆盖率统计文件到服务器进行覆盖率统计分析。

    较佳地,所述覆盖率统计服务端还用于:

    分布式执行管理,具体包括覆盖率统计任务的分发,处理和结果收集,以及节点服务器的管理和状态监测。

    较佳地,覆盖率统计服务端还用于支持覆盖率结果详情查看,所述覆盖率结果详情包括以下内容中的至少一种:

    覆盖率数据库,存储有覆盖率、分支覆盖率、行覆盖率和新代码覆盖率中的至少一种;

    设置的覆盖率统计包含的各代码目录或文件的覆盖率统计情况列表;

    被测应用代码的概况数据展示;

    被测应用的覆盖率历史统计趋势图显示;

    被测应用的覆盖率历史统计数据列表显示。

    较佳地,所述覆盖率统计服务端部署在多个Windows服务器上,其中一个服务器作为主站点,其他服务器作为覆盖率统计的执行站点。

    在符合本领域常识的基础上,上述各优选条件,可任意组合,即得本发明各较佳实例。

    本发明的积极进步效果在于:本发明能够提供一站式Java覆盖率统计配置,自动化测试执行以及覆盖率结果查看等服务,为测试人员提供了便利。

    附图说明

    图1为本发明实施例1的一种Java代码覆盖率统计系统的系统框图。

    图2为本发明实施例1的Java代码覆盖率统计系统的系统架构图。

    图3为本发明实施例1的系统实施物理部署图。

    具体实施方式

    下面通过实施例的方式进一步说明本发明,但并不因此将本发明限制在所述的实施例范围之中。

    实施例1

    本实施例提供了一种Java代码覆盖率统计系统。如图1所示,所述Java代码覆盖率统计系统包括:覆盖率统计服务客户端10和覆盖率统计服务端20。

    所述覆盖率统计服务客户端10是被安装被测应用所在服务器上的Web服务,主要用于:启停被测应用所在Web容器(比如Tomcat)、加载或卸载Jacoco相应的启动参数到Web容器的启动文件中、下载Jacoco产生的覆盖率统计文件中的至少一种。

    所述覆盖率统计服务端20可以用于提供多种服务,具体包括:覆盖率统计配置,系统覆盖率统计,单元测试覆盖率统计,代码质量静态检查,增量覆盖率统计,一键覆盖率统计,分布式执行管理,覆盖率结果查询,覆盖率结果详情查看。当然,本实施例并不局限于此,测试人员可以根据需求增加或删减部分服务。下面对各服务进行详细说明:

    (1)覆盖率统计配置,具体可以包括:

    A.忽略模块配置:如在Java的Maven项目中,经常会有多模块的项目,通过该设置,可以在编译以及统计覆盖率时忽略某些模块;

    B.覆盖率包含配置:如通过可视化树状代码结构,可以对需要覆盖率统计的目录和代码进行勾选,最后覆盖率统计结果就只包含选择目录和代码的覆盖率;

    C.覆盖率排除配置:通过可视化树状代码结构,可以对不需要覆盖率统计的目录和代码进行勾选,最后覆盖率统计结果就会排除掉选择的目录和代码的覆盖率。

    (2)系统覆盖率统计,具体包括:

    通过所述覆盖率统计服务客户端10在被测应用的启动过程中把Jacoco插桩到被测应用的JVM进程中,以捕获应用过程中产生的第一覆盖率数据,所述覆盖率统计服务端20通过所述第一覆盖率数据进行系统级别的覆盖率统计。

    (3)单元测试覆盖率统计,具体包括:

    从Git服务器拉取单元测试用例代码到本地服务器,通过执行Jacoco-maven-plugin插件获取单元测试的第二覆盖率数据,将所述第二覆盖率数据交由SonarQube进行单元测试的覆盖率统计。

    (4)代码质量静态检查,具体包括:

    从Git服务器拉取代码到本地服务器,通过执行sonar-maven-plugin插件把代码交由SonarQube进行代码静态扫描。

    (5)增量覆盖率统计,具体包括:

    比对两个版本中新增代码的覆盖率,通过增量覆盖率统计,测试人员可以很清晰的了解新版本中新增功能的覆盖情况,进而提高回归测试的质量。

    (6)一键覆盖率统计,具体包括:

    通过与API,UI自动化测试的整合,在开启覆盖率统计后,调用配置的API或UI自动化测试平台的接口执行自动化测试平台中配置的测试用例,获取所述自动化测试平台执行完毕后的反馈结果,通过所述覆盖率统计服务客户端10拉取覆盖率统计文件到服务器进行覆盖率统计分析,分析完毕后用户就可以查看应用的覆盖率统计情况了。

    (7)分布式执行管理,具体包括:

    A.覆盖率统计任务的分发,处理和结果收集,实现了任务的并行处理,有效的减少了服务器的负载;

    B.节点服务器的管理(包括增删改)和状态监测。

    (8)支持所述覆盖率统计服务客户端10查询覆盖率统计结果:

    覆盖率结果查询可以便捷的查询本组,本人覆盖率统计的详细信息.同时用户也可以下载覆盖率查询结果。

    (9)支持覆盖率结果详情查看

    为了使用户可以更清晰,更全面的了解自己应用的覆盖率统计情况,所述覆盖率结果详情主要包括以下内容中的至少一种:

    A.覆盖率数据库,存储有覆盖率、分支覆盖率、行覆盖率和新代码覆盖率中的至少一种;

    B.设置的覆盖率统计包含的各代码目录或文件的覆盖率统计情况列表;

    C.被测应用代码的概况数据展示,比如类,文件,行数,函数,单元测试数等情况;

    D.被测应用的覆盖率历史统计趋势图显示;

    E.被测应用的覆盖率历史统计数据列表显示。

    本实施例使测试人员可以很方便的实现单元测试,集成测试的代码覆盖率的统计和结果查看。通过与API,UI自动化结合,可以对测试用例查漏补缺,完善测试用例对功能的覆盖,提高被测系统的质量。

    图2示出了本实施例的Java代码覆盖率统计系统的系统架构图,其中,Spring MVC/MyBatis/Maven/Sonar作为基础架构技术,本实施例的系统构建在这些技术之上。

    本实施例的系统覆盖率支持的测试类型可以包括:

    A.测试环境:单元测试、API自动化测试前置、UI自动化测试、手动测试;

    B.UAT环境:API/UI自动化测试、验证测试。

    用户的基本操作流程为:

    A.创建覆盖率统计项;

    B.部署覆盖率统计服务客户端10;

    C.打开覆盖率统计开关;

    D.执行手动/自动化测试用例;

    E.关闭覆盖率统计开关;

    F.等待统计完成后,查看覆盖率统计结果。

    用户进行单元测试覆盖率统计的流程为:

    A.开启单元测试覆盖率统计;

    B.等待统计完成后,查看单元测试覆盖率统计结果。

    用户进行静态代码扫描的流程为:

    A.开启静态代码扫描;

    B.等待扫描完毕后,查看静态代码扫描结果。

    用户进行一键覆盖率统计的流程为:

    A.开启一键覆盖率统计;

    B.等待统计完成后,查看覆盖率统计结果。

    用户进行增量覆盖率统计的流程为:

    A.开启增量覆盖率统计开关;

    B.进行相关的测试(比如API测试,UI自动化测试,手工测试等);

    C.完成测试后关闭增量覆盖率统计开关;

    D.等待统计完成后,查看增量覆盖率统计结果。

    图3示出了本实施例的系统实施物理部署图。所述覆盖率统计服务端20可以部署在多个Windows服务器上,其中一个服务器作为主站点,其他服务器作为覆盖率统计的执行站点。用户通过浏览器访问Java覆盖率统计主站点就可以进行覆盖率统计的各种操作。

    虽然以上描述了本发明的具体实施方式,但是本领域的技术人员应当理解,这些仅是举例说明,本发明的保护范围是由所附权利要求书限定的。本领域的技术人员在不背离本发明的原理和实质的前提下,可以对这些实施方式做出多种变更或修改,但这些变更和修改均落入本发明的保护范围。

    展开全文
  • 1.效果如下: 2.HTML的代码如下: <div id="myChart" :style="{width: '1200px', height: '300px'}"></div> 3.JS里的代码如下: drawLine(){ let myChart = this.$echarts.init(document....

    最近在写一个事项管理系统,需要显示每月或每周结案与追踪的事项,图表如下:

    1. 效果图如下:

     2. HTML 的代码如下:

    <div id="myChart" :style="{width: '1200px', height: '300px'}"></div>

     

    3. JS 里的代码如下:

    drawLine(){
    
            let myChart = this.$echarts.init(document.getElementById('myChart'))
            // 绘制图表
            myChart.setOption({
    			title: { 
    					text: '项目追踪整体状况',
    					left:'center',
    					textStyle:{
    						//color:'#0DB9F2',        //颜色
    						fontStyle:'normal',     //风格
    						fontWeight:'normal',    //粗细
    						fontFamily:'Microsoft yahei',   //字体
    						fontSize:18,     //大小
    						align:'center',   //水平对齐
    						left:'center'
                    },
    					
    					},
    			
    			color: ['#00FF00', '#FF0000'],
    
    			grid:{
    				left: '5%', // 与容器左侧的距离
    				right: '5%', // 与容器右侧的距离
    				top: '12%', // 与容器顶部的距离
    				bottom: '15%', // 与容器底部的距离
    			},
    
    			legend: {
    				left: 'center',
    				top:'bottom',
    				data: ['已结案', '未结案']
    			},
                tooltip: {
    				//trigger: 'item',
                	//formatter: "{a} <br/>{b} : {c} ({d}%)"
    			},
    
            	xAxis: {
    				data: this.Monthx,
    			},
    			
    			yAxis: {},
    			barGap: '10%', 
                series: [
    			{
                    name: '已结案',
    				type: 'bar',
    				stack:'总量',
    				barWidth:49,
    				data: this.Closex,//这里在data数据里放完成的数据
    
    			},
    
    			{
                    name: '未结案',
    				type: 'bar',
    				stack:'总量',
    				data: this.Openx,//这里在data数据里放未结案的数据
    				label:{
    					show:true,
    					formatter:'{c}'
    				}
    
    			},
    			
    			]
            });
    	},

    4. 放进 Openx[] 与 Closex[] 数组里的数据格式如下:

        后端拿到数据后,使用push() 函数,按顺序放进数据里即可。

    Openx:[1,2,0,2,4,2,0,6],
    Closex:[10,6,8,6,12,9,6,9],

    5. 在开启页里调 用。

    mounted(){
        //调用之前要从后端拿到数据
        this.drawLine();
    }

    6.如有疑问可留言。

     

    展开全文
  • 项目管理:项目质量管理

    千次阅读 2021-01-15 10:09:41
    PMP指的是项目管理专业人士资格认证。它是由美国项目管理协会(Project Management Institute(PMI)发起的,严格评估项目管理人员知识技能是否具有高品质的资格认证考试。该文章内容基于PMBOK第六版总结而得。 重 ...
  • 本次开发基本完成 但过程中有一点让我及其在意,就是JS的执行效率。在改变了 某个地方 之后快了100倍 以下探究具体原因 可能原因1: 利用JSON+数组结构存储数据的行列(时间与数目)不同方式导致的数组个数不同 使得...
  • 2.将三台主机的CPU使用图形做成聚合图形 2.1.三台主机ip地址 IP 地址 192.168.81.220 192.168.81.230 192.168.81.250 2.2.创建聚合图形 点击监测—聚合图形—创建聚合图形 2.3.填写图形信息 名称:...
  • 图像分类项目 我们有了几十张宠物的图像,这些图像的种类都在ImageNet数据集中出现过,我们需要通过CNN模型来帮我们筛选比较一遍,顺便也对模型的识别结果和识别效率进行比较。 需要做的事情: 利用 Python 技能...
  • 软件项目管理知识点总结

    千次阅读 2020-12-27 18:18:16
    软件项目管理第1章 软件项目管理概述1、项目的基本概念(注意与日常运作的区分)和特征;2、软件项目及特征;3、项目管理的基本概念;4、项目管理知识体系(以2017年发布的PMBOK6的十个知识领域为准);5、适用于...
  • 首先要知道面试官都是抱着想把你招进来的想法的,只是想了解你的具体情况。既然面试官愿意花时间和你聊,那么证明自己还是有实力的,有被看中的闪光点,那么有什么好心虚的呢,勇敢自信的面对就好了。 为了让大家...
  • 最近,因为要展示项目的单元测试的代码覆盖,我无意间在网上找到了gcovr工具。使用之后,觉得这个工具相当的不错,于是便写下这篇文章,可供相关的开发人员参考。简而言之,gcovr是一个将单元测试中的代码覆盖...
  • 项目管理进阶——PMP 5A高分通过备考经验分享
  • 虽然照片能够记录那些幸福快乐的却不能够还原出当时那种喜悦的气氛,而使用相册视频比起一般的图片展示更为生动灵活,那么这段回忆也会变得生动起来。今天呢,小编找到一款可以快速制作电子相册的软件,所以小编接...
  • IT项目管理属于信管必修课,由孙老师授课出题,教材长下面这样,不过老师用的和学生用的教材不是同一个版本的,所以考试复习的时候会出现老师给的资料和学生教材不一样的情况。我个人认为,学生用的书比较容易理解,...
  • 前言—toG 项目——一个在我等日常工作中极为罕见、极为神秘的项目领域,所有经历过的人,都仿佛经受了一场狂风暴雨的洗礼,谁做谁知道。而数字人民币项目,光看名字就令人心生敬畏——新的货币形式...
  • (口诀在下中) 这个就是200页笔记,里头总结了历年高频考点 我自己就这些笔记整理了200页。这种口诀都放在里头了。当然不要求一字不落,拿满分。但是写一些内容总能拿几分,这部分评分是按点答题,答错...
  • 第一节实践环境和项目初识 一、采用百度aistudio在线环境(基于Notebook的python环境) 网址:https://aistudio.baidu.com/ 实验环境 启动环境后,选择基础版。高级版的只需要在迁移训练项目时使用 启动...
  • 同时,按时完成项目项目经历**最大的挑战之一**,时间是项目规划中**灵活性最小**的因素,且进度问题是项目**冲突的主要原因**。 因此,学好软件项目进度计划,对于每一个开发人员来说不可或缺。 下面就开始今天...
  • PMI-ACP敏捷项目认证练习题(一)

    千次阅读 2021-03-27 17:45:58
    声明:所有练习题目来自网络,如有侵权请告知。 1、团队重视培训新人的个人技能,...在第一次站会上,项目经理主要到团队成员对完成项目感到焦虑,成员还因为职能经理的频繁中断和请求经理分散。这属于哪一种组织类型
  • 敏捷项目管理学习

    2021-01-03 03:14:47
    7、敏捷项目管理方法:XP、ASD、FDD、TDD、Crystal、DDSM、AUP;8、产品愿景声明和产品路线;9、用户故事;10、Product Backlog和Sprint Backlog;11、冲刺主要工作、敏捷角色及分工;12、不同折线的燃尽所说明...
  • 工程背景介绍:我们开发了一个万能接口,用户通过这个接口中传入数据,我们拿到数据进行复杂的逻辑处理然后再将数据各种匹配展示分发等操作,...项目出现问题:我们以为自己的程序就像上中的那样运行,一次请求,...
  • 一、创建新的版本库 创建一个版本库来分享我们的项目,通过点击面板右侧的...除了一个必须要填的项目名,其他字段都是可选的。现在只需要点击 “Create Repository” 按钮,就在 GitHub 上拥有了一个以 /<project_
  • 项目质量管理流程:(考点:描述场景区分属于哪一个过程) ➢ 规划管理质量:确定某一规划,进行设定 ➢ 管理质量:管理过程 ➢ 控制质量:找偏差找原因找问题 ✧ 质量管理的方法: ➢ 戴明:戴明环、持续改进 ...
  • 软件项目进度计划)进度管理基本概念项目任务的关联关系任务之间关联关系的依据进度管理图示甘特网络(重点)里程碑燃尽工程评估评审技术(PERT)关键路径法CPM基本术语示例:项目要进度优化例题自练: ...
  • 1、项目管理定义 简单的描述一下:项目管理是一群人围绕一个共同的目标,为了达成目标,将目标层层拆解,形成一个非常有效的节奏(计划),成员依赖这...项目质量,也就是项目目标的高质量完成受限于项目范围、项目..
  • 短视频流行了起来,随着这股潮流,一种动图封面的设计也被很短视频app采用:某音而在app中,动图的展示是比较消耗性能的操作,对于这种一页非常的动图在展示时需要做对应的处理,今天我结合自己在项目中处理的...
  • 一、引言我是一名中间件 QA,我对应的研发团队是有赞 PaaS,目前我们团队有很产品是使用 go 语言开发,因此我对 go 语言项目的单测覆盖、集成以及增量测试覆盖统计与分析做了探索。二、单测覆盖以及静态代码...
  • 最近帮朋友做一个图片数据分类的项目,借鉴了大佬的代码,修修改改,话不说直接上代码! 一、图片转batch文件 import numpy as np from PIL import Image import operator from os import listdir import sys ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 63,909
精华内容 25,563
热门标签
关键字:

多项目完成率展示图