excel+requests管理测试用例接口自动化框架

news2025/1/15 19:55:21

背景:

某项目有多个接口,之前使用的unittest框架来管理测试用例,将每个接口的用例封装成一个py文件,接口有数据或者字段变动后,需要去每个py文件中找出变动的接口测试用例,维护起来不方便,为了便于接口变动后维护,使用excel来管理测试用例,接口有变动不需要修改代码,只需要维护excel即可。

思路:

为了方便维护测试用例,一个接口的测试用例使用一个excel文件来管理,每个excel文件中有两个sheet页,第一个sheet页是接口的基本信息,包括接口名称,地址和请求方式,第二个sheet页为接口的测试用例,如下图所示

第一个sheet页

第二个sheet页

 接口请求的数据类型为X-WWW-FORM-URLENCODED,在测试用例中每个字段为一列,每条用例为一行,倒数第二列为预期结果,倒数第三列为该条用例的描述。

接口自动化框架结构:

common目录存放公共的方法,例如写日志,连数据库

config目录存放配置文件和读取配置文件内容的方法,cfg.ini包括发送邮件的配置信息和接口的ip和端口

data目录存放接口的测试用例

logs目录存放用例执行的日志

report目录存放测试报告

run_main.py为用例执行的入口

源码:api_test.py封装读取测试用例的数据,执行测试用例和校验测试结果


#coding:utf-8

import xlrd,os
import requests
from datetime import datetime
from xlrd import xldate_as_tuple
from config import readConfig
from common.logger import Log

'''
获取测试用例data所在的目录
'''
d = os.path.dirname(__file__) #返回当前文件所在目录(common文件夹路径)
parent_path = os.path.dirname(d) #返回common的父级目录
data_path = os.path.join(parent_path,'data') #返回data所在目录
data_path1 = os.listdir(data_path) #返回data目录下所有的文件

log = Log()

def api_data():
    for filename in data_path1:
        book = xlrd.open_workbook(os.path.join(data_path,filename))

        '''
        获取excel文件中接口信息
        '''
        table = book.sheet_by_index(0) #通过索引,获取相应的列表,这里表示获取excel的第一个列表
        inf_name = table.row_values(1)[0] #返回接口名称
        inf_address = table.row_values(1)[1] #返回接口地址
        inf_mode = table.row_values(1)[2] #返回请求方式

        '''
        获取excel文件中测试用例信息
        '''
        sheet = book.sheet_by_index(1) #通过索引,获取相应的列表,这里表示获取excel的第二个列表
        nrows = sheet.nrows #获取所有行数
        filed = sheet.row_values(0)
        # print(filed)

        for i in range(1,nrows):
            d1 = {}
            for j in range(0,len(filed)-2):
                ctype = sheet.cell(i, j).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, j)
                d = {}
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                # print(cell)
                d.update({filed[j]:cell})
                # print(d)
                d1.update(d)
            # print(d1)

            '''
            获取excel文件中测试用例预期结果和描述
            '''
            a = []
            for k in range(len(filed)-2,len(filed)):
                ctype = sheet.cell(i, k).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, k)
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                a.append(cell)
            # print(a[0])
            # print(type(a[0]))

            '''
            获取cfg.ini配置文件中接口公共信息(ip和port)
            '''
            ip = readConfig.ip  # 获取配置文件中接口ip
            i_port = readConfig.i_port  # 获取配置文件中接口port
            url = "http://" + ip + ":" + i_port + inf_address
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
                "X-Requested-With": "XMLHttpRequest",
                "Connection": "keep-alive"
            }
            par = d1

            '''
            判断请求方式是GET还是POST,并且判断测试用例预期结果与实际响应一致
            '''
            if inf_mode == 'GET':
                r = requests.get(url, params=par)
                result = r.json()
                # log.info("---编号%s,接口名称%s---")%(i,inf_name)
                print(inf_name, str(result).replace('None','null'), a[1])
                if str(result).replace('None','null') == a[0]:
                    log.info("pass")
                    log.info("--------")
                else:
                    log.info("false")
                    log.info("--------")
            elif inf_mode == 'POST':
                r = requests.post(url, data=par, headers=headers)
                result = r.json()
                print(inf_name, str(result).replace('None', 'null'), a[1])
                if str(result).replace('None', 'null') == a[0]:
                    print('pass')
                    print('--------')
                else:
                    print('false')
                    print('--------')


api_data()

配置文件cfg.ini(主要配置邮箱和接口ip+port等常用数据信息)


[email]

smtp_server = smtp.163.com
port = 465
sender = xxx;psw是QQ邮箱的授权码
psw = xxx

;收件人多个时,中间用逗号隔开,如'a@xx.com,b@xx.com'
receiver = xxx[interface]

ip = xxx
;接口ip
port = xxx
;接口端口

readConfig.py读取配置文件中数据


# coding:utf-8
import os
import configparser

cur_path = os.path.dirname(os.path.realpath(__file__))
configPath = os.path.join(cur_path, "cfg.ini")
conf = configparser.ConfigParser()
conf.read(configPath,encoding='utf-8')


smtp_server = conf.get("email", "smtp_server")

sender = conf.get("email", "sender")

psw = conf.get("email", "psw")

receiver = conf.get("email", "receiver")

port = conf.get("email", "port")

ip = conf.get("interface","ip")

i_port = conf.get("interface","port")

优化:

部分接口访问时,响应未知用户,需要用session关联接口,先调用登录接口,把登录接口的调用封装成了一个实例方法,实现了复用,登录之后,登录接口的http响应会把session以 cookie的形式set到客户端,之后的接口都会使用此session去请求封装登录接口user_login.py


#coding:utf-8
import requests
from common.logger import Log

class Login():
    log = Log()

    def __init__(self,s):
        self.s = s

    def login(self,code,passwd):
        url = "http://192.168.20.100:8081/backend/system/user/login"
        headers = {"Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
                   "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36",
                   "X-Requested-With":"XMLHttpRequest",
                   "Cookie":"JSESSIONID=92D7FB4C7FB917B7D2E8DC429A63443F",
                   "Connection":"keep-alive"
                  }
        d = {"code":code,"passwd":passwd}

        res = self.s.post(url,headers=headers,data=d)
        result1 = res.text #字节输出
        self.log.info(u"调用登录方法,获取结果:%s"%result1)
        return res.json()

优化api_test.py中部分代码(红色部分为优化的代码)

1.在请求接口前首先调用登录接口2.加入执行用例的编号(p),每循环一次自增1


#coding:utf-8

import xlrd,os
import requests
from datetime import datetime
from xlrd import xldate_as_tuple
from config import readConfig
from common.logger import Log
from case.user_login import Login

'''
获取测试用例data所在的目录
'''
d = os.path.dirname(__file__) #返回当前文件所在目录(common文件夹路径)
parent_path = os.path.dirname(d) #返回common的父级目录
data_path = os.path.join(parent_path,'data') #返回data所在目录
data_path1 = os.listdir(data_path) #返回data目录下所有的文件

s = requests.session()
lon = Login(s)
log = Log()


def api_data():
    p = 1
    for filename in data_path1:
        book = xlrd.open_workbook(os.path.join(data_path,filename))

        '''
        获取excel文件中接口信息
        '''
        table = book.sheet_by_index(0) #通过索引,获取相应的列表,这里表示获取excel的第一个列表
        inf_name = table.row_values(1)[0] #返回接口名称
        inf_address = table.row_values(1)[1] #返回接口地址
        inf_mode = table.row_values(1)[2] #返回请求方式

        '''
        获取excel文件中测试用例信息
        '''
        sheet = book.sheet_by_index(1) #通过索引,获取相应的列表,这里表示获取excel的第二个列表
        nrows = sheet.nrows #获取所有行数
        filed = sheet.row_values(0)
        # print(filed)

        for i in range(1,nrows):
            d1 = {}
            for j in range(0,len(filed)-2):
                ctype = sheet.cell(i, j).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, j)
                d = {}
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                # print(cell)
                d.update({filed[j]:cell})
                # print(d)
                d1.update(d)
            # print(d1)

            '''
            获取excel文件中测试用例预期结果和描述
            '''
            a = []
            for k in range(len(filed)-2,len(filed)):
                ctype = sheet.cell(i, k).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, k)
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                a.append(cell)
            # print(a[0])
            # print(type(a[0]))

            '''
            获取cfg.ini配置文件中接口公共信息(ip和port)
            '''
            ip = readConfig.ip  # 获取配置文件中接口ip
            i_port = readConfig.i_port  # 获取配置文件中接口port
            url = "http://" + ip + ":" + i_port + inf_address
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
                "X-Requested-With": "XMLHttpRequest",
                "Connection": "keep-alive"
            }
            par = d1

            '''
            判断请求方式是GET还是POST,并且判断测试用例预期结果与实际响应一致,所有接口请求前先调用登录接口
            '''
            code = "xxx"  #登录接口用户code
            passwd = "xxx" #登录接口用户passwd
            lon.login(code, passwd)

            if inf_mode == 'GET':
                r = s.get(url, params=par)
                result = r.json()
                log.info("编号:%s,接口名称:%s,测试点:%s,响应:%s"%(p,inf_name,a[1],str(result).replace('None','null')))
                # print(inf_name, str(result).replace('None','null'), a[1])
                if str(result).replace('None','null') == a[0]:
                    log.info("pass")
                    log.info("--------")
                else:
                    log.info("false")
                    log.info("--------")
            elif inf_mode == 'POST':
                r = s.post(url, data=par, headers=headers)
                result = r.json()
                log.info("编号:%s,接口名称:%s,测试点:%s,响应:%s" % (p, inf_name,a[1],str(result).replace('None', 'null')))
                # print(inf_name, str(result).replace('None', 'null'), a[1])
                if str(result).replace('None', 'null') == a[0]:
                    log.info("pass")
                    log.info("--------")
                else:
                    log.info("false")
                    log.info("--------")

            p=p+1

api_data()

执行结果:

优化二:

excel中添加结果列,将每条用例的执行结果写入excel中,因为excel版本是2007以上,采用openpyxl模块去修改excel单元格的值,执行通过用绿色字体标注pass,执行不通过的用例红色字体标注false优化api_test.py中部分代码


#coding:utf-8

import xlrd,os
import requests
import openpyxl
from openpyxl.styles import Font
# from xlutils.copy import copy
from datetime import datetime
from xlrd import xldate_as_tuple
from config import readConfig
from common.logger import Log
from case.user_login import Login


'''
获取测试用例data所在的目录
'''
d = os.path.dirname(__file__) #返回当前文件所在目录(common文件夹路径)
parent_path = os.path.dirname(d) #返回common的父级目录
data_path = os.path.join(parent_path,'data') #返回data所在目录
data_path1 = os.listdir(data_path) #返回data目录下所有的文件

s = requests.session()
lon = Login(s)
log = Log()


def api_data():
    p = 1


    for filename in data_path1:
        book = xlrd.open_workbook(os.path.join(data_path,filename))

        '''
        使用xlwt操作excel,xlwt只支持excel2007以下版本
        '''

        # wb = copy(book)
        # ws = wb.get_sheet(1)

        '''
        使用openpyxl操作excel,openpyxl支持excel2007以上版本
        '''
        wb = openpyxl.load_workbook(os.path.join(data_path,filename))
        ws = wb.worksheets[1]
        font_green = Font(color="37b400")
        font_red = Font(color="ff0000")


        '''
        获取excel文件中接口信息
        '''
        table = book.sheet_by_index(0) #通过索引,获取相应的列表,这里表示获取excel的第一个列表
        inf_name = table.row_values(1)[0] #返回接口名称
        inf_address = table.row_values(1)[1] #返回接口地址
        inf_mode = table.row_values(1)[2] #返回请求方式

        '''
        获取excel文件中测试用例信息
        '''
        sheet = book.sheet_by_index(1) #通过索引,获取相应的列表,这里表示获取excel的第二个列表
        nrows = sheet.nrows #获取所有行数
        ncols = sheet.ncols #获取所有列数
        filed = sheet.row_values(0)
        # print(filed)

        for i in range(1,nrows):
            d1 = {}
            for j in range(0,len(filed)-3):
                ctype = sheet.cell(i, j).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, j)
                d = {}
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                # print(cell)
                d.update({filed[j]:cell})
                # print(d)
                d1.update(d)
            # print(d1)

            '''
            获取excel文件中测试用例预期结果和描述
            '''
            a = []
            for k in range(len(filed)-3,len(filed)-1):
                ctype = sheet.cell(i, k).ctype  # 表格的数据类型
                cell = sheet.cell_value(i, k)
                if ctype == 2 and cell % 1 == 0:  # 如果是整形
                    cell = int(cell)
                elif ctype == 3:
                    # 转成datetime对象
                    date = datetime(*xldate_as_tuple(cell, 0))
                    cell = date.strftime('%Y/%m/%d')
                elif ctype == 4:
                    cell = True if cell == 1 else False
                a.append(cell)
            # print(a[0])
            # print(type(a[0]))

            '''
            获取cfg.ini配置文件中接口公共信息(ip和port)
            '''
            ip = readConfig.ip  # 获取配置文件中接口ip
            i_port = readConfig.i_port  # 获取配置文件中接口port
            url = "http://" + ip + ":" + i_port + inf_address
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0",
                "X-Requested-With": "XMLHttpRequest",
                "Connection": "keep-alive"
            }
            par = d1

            '''
            判断请求方式是GET还是POST,并且判断测试用例预期结果与实际响应一致,所有接口请求前先调用登录接口
            '''
            code = "xuxingan"
            passwd = "admin"
            lon.login(code, passwd)



            if inf_mode == 'GET':
                r = s.get(url, params=par)
                result = r.json()
                log.info("编号:%s,接口名称:%s,测试点:%s,响应:%s"%(p,inf_name,a[1],str(result).replace('None','null')))
                # print(inf_name, str(result).replace('None','null'), a[1])
                if str(result).replace('None','null') == a[0]:
                    # ws.write(i,ncols-1,'pass'.encode('utf-8'))
                    ws.cell(row=i+1,column=ncols,value='pass').font = font_green
                    log.info("pass")
                    log.info("--------")
                else:
                    # ws.write(i,ncols-1,'false'.encode('utf-8'))
                    ws.cell(row=i+1, column=ncols, value='false').font = font_red
                    log.info("false")
                    log.info("--------")
            elif inf_mode == 'POST':
                r = s.post(url, data=par, headers=headers)
                result = r.json()
                log.info("编号:%s,接口名称:%s,测试点:%s,响应:%s" % (p, inf_name,a[1],str(result).replace('None', 'null')))
                # print(inf_name, str(result).replace('None', 'null'), a[1])
                if str(result).replace('None', 'null') == a[0]:
                    # ws.write(i,ncols-1,'pass'.encode('utf-8'))
                    ws.cell(row=i+1, column=ncols, value='pass').font = font_green
                    log.info("pass")
                    log.info("--------")
                else:
                    # ws.write(i,ncols-1,'false'.encode('utf-8'))
                    ws.cell(row=i+1, column=ncols, value='false').font = font_red
                    log.info("false")
                    log.info("--------")
            wb.save(os.path.join(data_path, filename))
            p=p+1


    log.info("总计%s条用例"%p)

api_data()

执行结果

总结:

第一个版本有点粗糙,1.后续加入将每条用例的执行结果写入测试用例excel文件 2.生成自动化测试报告

Python接口自动化测试零基础入门到精通(2023最新版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1099227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记IIS升级迁移之旅

场景 有一台Windows Server 2008机器,因为操作系统更新的原因,需要升级到 2022, 这台机器上原先部署了IIS 应用, 所以需要一并迁移。 旧机器: Windows Server 2008 , IIS7 ,.NET 版本v4.0新机…

qt笔记之qml下拉标签组合框增加发送按钮发送标签内容

qt笔记之qml下拉标签组合框增加发送按钮发送标签内容 code review! 文章目录 qt笔记之qml下拉标签组合框增加发送按钮发送标签内容1.运行2.文件结构3.main.qml4.main.cc5.MyClass.h6.MyClass.cc7.CMakeLists.txt8.ComboBox.pro9.qml.qrc 1.运行 2.文件结构 3.main.qml 代码 …

Android自定义AppGlideModule,DataFetcher ,ModelLoaderFactory,ModelLoader,Kotlin(1)

Android自定义AppGlideModule,DataFetcher ,ModelLoaderFactory,ModelLoader,Kotlin(1) 假设实现一个简单的功能,对传入要加载的path路径增加一定的筛选、容错或“重定向”,需要自定义一个模型,基于这个模型,让Glide自动匹配模型…

logback服务器日志删除原理分析

查看以下的logback官方文档 Chapter 4: Appendershttps://logback.qos.ch/manual/appenders.html 按文档说明,maxHistory是设置保存归档日志的最大数量,该数量的单位受到fileNamePattern里的值%d控制,如果有多个%d,只能有一个主%d&#xff0…

ArcGIS笔记8_测量得到的距离单位不是米?一经度一纬度换算为多少米?

本文目录 前言Step 1 遇到测量结果以度为单位的情况Step 2 简单的笨办法转换为以米为单位Step 3 拓展:一经度一纬度换算为多少米 前言 有时我们会遇到这种情况,想在ArcGIS中使用测量工具测量一下某一段距离,但显示的测量结果却是某某度&…

Linux操作系统的基础知识

在操作系统中,进程的执行也需要分配 CPU 进行执行,也就是按照程序里面的二进制代码一行一行地执行。于是,为了管理进程,我们还需要一个进程管理子系统(Process Management Subsystem)。如果运行的进程很多&…

java基础练习,九九乘法表(java版),计算器

简介 对于有了解,但是了解不深的同学,学习Java总是感觉一看就会,一些就废。往往需要一些实操练习,来夯实我们的学习结果。九九乘法表和计算器都是在编程学习领域比较经典的案例。本文为大家讲解一下两个基础练习涉及到一些基础知…

VS2010 C语言内嵌汇编语言程序

VS2010 C语言内嵌汇编语言程序 2021年7月28日席锦 在visual studio 2010中C语言使用内联汇编写代码 ,它的格式有两种, 一种是__asm 直接接汇编指令语句,比如:__asm int 3 // 软件中断 另一种是加上花括号,类似于一个函数&…

Python库学习(十):Matplotlib绘画库

1. 介绍 Matplotlib 是一个用于绘制图表和可视化数据的 Python 库。它提供了丰富的绘图工具,可以用于生成各种静态、交互式和动画图表。Matplotlib 是数据科学、机器学习和科学计算领域中最流行的绘图库之一。 1.1 关键特性 以下是 Matplotlib 的一些关键特性&…

23基于MATLAB的小波降噪,默认阈值消噪,强制消噪,给定软阈值消噪方法,数据直接替换后就可以跑。

基于MATLAB的小波降噪,默认阈值消噪,强制消噪,给定软阈值消噪方法,数据直接替换后就可以跑。 https://www.xiaohongshu.com/explore/652d57c600000

Leetcode刷题解析——904. 水果成篮

1. 题目链接:904. 水果成篮 2. 题目描述: 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主…

vue 拿到数据后,没有重新渲染视图,nuxt.js拿到数据后,没有重新渲染视图,强制更新视图

以下为Vue2的解决方案 一、 Vue.set() 问:什么情况下使用? 答:如果你向响应式数据添加新的“属性”,理论上,一般情况下是没问题的,但是,如果你的级别比较深,又…

Py之trl:trl(一款采用强化学习训练Transformer语言模型和稳定扩散模型的全栈库)的简介、安装、使用方法之详细攻略

Py之trl:trl(一款采用强化学习训练Transformer语言模型和稳定扩散模型的全栈库)的简介、安装、使用方法之详细攻略 目录 trl的简介 1、亮点 2、PPO是如何工作的:PPO对语言模型微调三步骤,Rollout→Evaluation→Optimization trl的安装 t…

LeetCode 2 两数相加

题目描述 链接:https://leetcode.cn/problems/add-two-numbers/?envTypefeatured-list&envId2ckc81c?envTypefeatured-list&envId2ckc81c 难度:中等 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式…

软件设计之工厂方法模式

工厂方法模式指定义一个创建对象的接口,让子类决定实例化哪一个类。 结构关系如下: 可以看到,客户端创建了两个接口,一个AbstractFactory,负责创建产品,一个Product,负责产品的实现。ConcreteF…

基于ssm008医院门诊挂号系统+jsp【附PPT|开题|任务书|万字文档(LW)和搭建文档】

主要功能 后台登录:4个角色 管理员: ①个人中心、修改密码、个人信息 ②药房管理、护士管理、医生管理、病人信息管理、科室信息管理、挂号管理、诊断信息管理、病例库管理、开药信息管理、药品信息管理、收费信息管理 药房: ①个人中心、修…

CSS阶详细解析一

CSS进阶 目标:掌握复合选择器作用和写法;使用background属性添加背景效果 01-复合选择器 定义:由两个或多个基础选择器,通过不同的方式组合而成。 作用:更准确、更高效的选择目标元素(标签)。…

计算机算法分析与设计(11)---贪心算法(活动安排问题和背包问题)

文章目录 一、贪心算法概述二、活动安排问题2.1 问题概述2.2 代码编写 三、背包问题3.1 问题描述3.2 代码编写 一、贪心算法概述 1. 贪心算法的定义:贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以…

CICD 流程学习(四)搜素服务与消息队列

一 搜索服务 1 Lucene概念 Lucene是一种高性能、可伸缩的信息搜索 (IR)库,在2000年开源,最初由鼎鼎大名的Doug Cutting开发。是基于Java实现的高性能的开源项目 Lucene采用了基于倒排表的设计原理,可以非常高效地实现文本查找&#xff0…

GEO生信数据挖掘(九)WGCNA分析

第六节,我们使用结核病基因数据,做了一个数据预处理的实操案例。例子中结核类型,包括结核,潜隐进展,对照和潜隐,四个类别。第七节延续上个数据,进行了差异分析。 第八节对差异基因进行富集分析。…