2023年3月

有人说研发效能是老板工程。不是的,研发效能不是老板工程,它不直接服务于老板(虽然老板可能看一些报表),反而是服务于广大产研运(产品+研发+质量+运维)的同学
,所以有的公司也把研发效能叫做基础中台,平台工程,开发者服务团队,或者叫开发者服务平台。做好研发效能,做好开发者中台,就容易把公司的各种中后台能力如同积木般不断组装成一个个的业务能力推给用户。当然如果老板有效能的意识,有决心和动力提高公司的产研效能,为广大的产研小伙伴提供一个比较好的开发者服务基础设施,那当然是就更好了。

前期优先发展主营业务

老板们大多数结果为先,国内企业大多数也是注重自己主营业务,业务为先,业绩为先。

当公司营收,依然还在快速上升时期,主营业务持续向好时,通过增加人力资源依然可以推高主营业务营收,只要人力成本依然可以接受的时候,老板一般都会选择快速补人头来继续催化营收,而不是注重研发效能方面的提高。当然也有一些一直高举高打各方面投入都很高的公司,比如某二进制公司,即便这样前期的效能相关职能也是四散在公司各个业务线,乱的很。

考虑的主要因素:

  • 1)立马可行,见效快,短期能补充

  • 2)补充人力,成本短期也可接受

  • 3)见效快。研发效能短期投入虽不高,但见效慢

  • 4)大老板们对研发效能的理解还在提升阶段

中期各地建基地抢人头

上面这种堆人催化业务发展这种情况的上限不高。因为在一个城市里能提供的人力毕竟是有限的,当想发展得更快时,只能加钱招人,即便这样很多公司还招不到。这也就造成了互联网公司都是全国各地建分基地抢人。

想做搜索去北京,挨着百度建分公司;想做电商去浙江,就在阿里旁边;做游戏那就去深圳挖腾讯、网易。如果一个分基地还不满足那就建两个。我国IT人才比较多的省份如下:北京、广东、江苏、上海、浙江、四川、湖北。

研发效能、修炼内功

如果多个分基地还不能满足业务发展,或者公司内已经人满为患但是依然业务不够快,这个时候就要好好考虑下公司的人效了,尤其是产研运的效率。

这就像一个人学武的前期阶段,虽然每个人选择的方向不同,但是只要在某一方向上下功夫,肯定能快速让自己的武功爬升到一个层级。有的善于拳术、有的精于腿法、有的强于兵器、有的则善用暗器。如果还要武功精进,则要修炼内功心法。修炼内功对自己的武功之前修炼的招式有莫大的增益,同时还能有助于修炼其他武功,触类旁通。

研发效能如同九阳神功,实打实的内功心法,需要长期修炼,才能形成无上内功。虽然研发效能一般不能短期对主营业务产生直接影响,但是一旦成型增益你出招的速度,力量和准确度,也很容易地把之前拳术能力运用到腿法、兵器、暗器上。

研发效能工作的特点

  • 1)长期投入,专业人才不好找

  • 2)做的事情多,投入相对分散,比如各种基建需要做

  • 3)见效相对慢,工具平台的建设非一朝一夕

  • 4)好在任督二脉一旦打通,事半功倍,效果显著且持久

但研发效能也有危险,修炼不好,容易走火入魔,比如很多公司都魔怔式的统计工时,不知道是向甲方收钱,还是觉得员工辛苦想奖励员工,还有一些拿些虚假繁荣的指标忽悠别人忽悠领导。汝之蜜糖,彼之砒霜。

开发者服务

开发者服务是指为开发者提供的各种工具和服务,以便他们更加高效地进行软件开发。

  • 版本控制系统

  • 基础设施服务

  • 编程语言、组件和框架

  • 调试和测试工具

  • CI/CD工具

  • 文档和知识库

  • 社区和论坛

以上是一些常见的开发者服务,它们可以帮助开发者更加高效地进行软件开发。

本文总结

本文主要陈述了研发效能不是一个老板工程,面子工程,而是实实在在的为产研运小伙伴服务的职能。让大家利用公司的基础设施和平台服务,顺顺畅畅的工作,高效的产出这才是我们做研发效能的目的。

推荐阅读

研发效能负责人/研发效能1号位|DevOps负责人
产品经理,项目经理,FTO
研发效能DevOps推荐书单
研发效能|DevOps 已死平台工程永存带来的焦虑
企业内源(内部开源)问与答
高效能敏捷交付团队反思:特性团队(FeatureTeam)+Scrum

前面已经下载好了Android源码,可以在对应目录下构建二次开发后的monkey jar包了;

当前环境:Ubuntu16.04,Andorid10源码。

1.初始化环境

cd进入android源码根目录,执行source build/envsetup.sh 初始化环境;

执行成功没有什么提示信息;

2.
修改Android.mk配置文件

只构建monkey,需修改Android.mk配置文件;

/android_10/development/cmds/monkey/Android.mk


增加一行: LOCAL_DEX_PREOPT:=false

3.
执行make monkey

执行成功后有完成提示信息;

4.
指定目录下可找到jar包

/android_10/out/target/product/generic/system/framework

5.
jar包推到手机/sdcard,可调起执行

终端执行命令:

adb push monkey.jar /sdcard

adb shell CLASSPATH=/sdcard/monkey.jar exec app_process /system/bin com.android.commands.monkey.Monkey --ignore-security-exceptions 600

能够调起执行随机测试即可;


后面就可以按需修改monkey源码,并构建jar包执行到安卓设备上了。

6.
Android6.0.1版本make问题记录

最近发现base在android10上的jar包运行在低版本无法调起测试,且没有报错信息,看起来是未进入monkey;

为了节约时间先base在Android6.0.1上开发了,低版本构建会有些其它问题,这里记录下;
  • Android6.0.1 make jar包需要OPEN JDK1.7版本;

OPEN JDK1.7版本的包比较老很难找,直接粘贴到这;

链接:
https://pan.baidu.com/s/1FSIkN7ooz1tBBCnZ-6B80A
提取码: iwbw

解压后将路径配置到java环境变量即可;(gedit ~/.bashrc)

  • Make monkey提示需要openjdk1.7.x,但你的版本是openjdk1.7;

这里确认本地环境已经配置好1.7了,提示很奇怪,可以临时修改下配置文件越过这个问题,感觉是bug;

修改android文件夹下的 /build/core/main.mk 配置文件修改下,对应修改如下:
再执行应该就可以了;

首先我们需要创建一个
MasaFramework
模板的项目,项目名称
TokenDemo
,项目类型如图所示

删除
Web/TokenDemo.Admin
项目,新建
Masa Blazor Pro
项目模板

项目,项目位置在
src/Web
项目

项目类型选择
ServerAndWasm
,为了让我们支持俩种模式

创建完成以后的目录,然后在
TokenDemo.Admin
中添加项目引用
TokenDemo.Caller

配置
EntityFrameworkCore

Sqlite

修改
TokenDemo.Service
项目的包依赖为预览版

	<ItemGroup>
		<PackageReference Include="Masa.BuildingBlocks.Dispatcher.Events" Version="1.0.0-preview.18" />
		<PackageReference Include="Masa.Contrib.Data.Contracts" Version="1.0.0-preview.18" />
		<PackageReference Include="Masa.Contrib.Data.EFCore.Sqlite" Version="1.0.0-preview.18" />
		<PackageReference Include="Masa.Contrib.Dispatcher.Events" Version="1.0.0-preview.18" />
		<PackageReference Include="Masa.Contrib.Dispatcher.IntegrationEvents.EventLogs.EFCore" Version="1.0.0-preview.18" />
		<PackageReference Include="FluentValidation" Version="11.5.1" />
		<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
		<PackageReference Include="Masa.Utils.Extensions.DependencyInjection" Version="1.0.0-preview.18" />
		<PackageReference Include="Masa.Contrib.Service.MinimalAPIs" Version="1.0.0-preview.18" />
		<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" />
		<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
	</ItemGroup>

Masa.Contrib.Data.Contracts
提供了
数据过滤
的能力, 但它不是必须的

然后会出现报错

LogMiddleware
将代码修改为以下代码

namespace TokenDemo.Service.Infrastructure.Middleware;

public class LogMiddleware<TEvent> : EventMiddleware<TEvent>
    where TEvent : notnull, IEvent
{
    private readonly ILogger<LogMiddleware<TEvent>> _logger;

    public LogMiddleware(ILogger<LogMiddleware<TEvent>> logger)
    {
        _logger = logger;
    }

    public override async Task HandleAsync(TEvent action, EventHandlerDelegate next)
    {
        var typeName = action.GetType().FullName;

        _logger.LogInformation("----- command {CommandType}", typeName);

        await next();
    }
}

ValidatorMiddleware
将代码修改为以下代码

namespace TokenDemo.Service.Infrastructure.Middleware;

public class ValidatorMiddleware<TEvent> : EventMiddleware<TEvent>
    where TEvent : notnull, IEvent
{
    private readonly ILogger<ValidatorMiddleware<TEvent>> _logger;
    private readonly IEnumerable<IValidator<TEvent>> _validators;

    public ValidatorMiddleware(IEnumerable<IValidator<TEvent>> validators, ILogger<ValidatorMiddleware<TEvent>> logger)
    {
        _validators = validators;
        _logger = logger;
    }

    public override async Task HandleAsync(TEvent action, EventHandlerDelegate next)
    {
        var typeName = action.GetType().FullName;

        _logger.LogInformation("----- Validating command {CommandType}", typeName);

        var failures = _validators
            .Select(v => v.Validate(action))
            .SelectMany(result => result.Errors)
            .Where(error => error != null)
            .ToList();

        if (failures.Any())
        {
            _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, action, failures);

            throw new ValidationException("Validation exception", failures);
        }

        await next();
    }
}

OrderEventHandler
将代码修改为以下代码

namespace TokenDemo.Service.Infrastructure.Handlers;

public class OrderEventHandler
{
    readonly IOrderRepository _orderRepository;

    public OrderEventHandler(IOrderRepository orderRepository)
    {
        _orderRepository = orderRepository;
    }

    [EventHandler(Order = 1)]
    public async Task HandleAsync(QueryOrderListEvent @event)
    {
        @event.Orders = await _orderRepository.GetListAsync();
    }
}

public class OrderEventAfterHandler : IEventHandler<QueryOrderListEvent>
{
    public async Task HandleAsync(QueryOrderListEvent @event, CancellationToken cancellationToken = new CancellationToken())
    {
        await Task.CompletedTask;
    }
}

修改
appsettings.json
添加
Sqlite
地址

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=Catalog.db;"
  }
}

修改
Program.cs
代码

using TokenDemo.Service.Infrastructure;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddAuthorization()
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.Authority = "";
        options.RequireHttpsMetadata = false;
        options.Audience = "";
    });

builder.Services.AddMasaDbContext<ShopDbContext>(dbContextBuilder =>
{
    dbContextBuilder
        .UseSqlite() //使用Sqlite数据库
        .UseFilter(); //数据数据过滤
});

builder.Services.AddAutoInject();
var app = builder.Services
    .AddEndpointsApiExplorer()
    .AddSwaggerGen(options =>
    {
        options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
        {
            Name = "Authorization",
            Type = SecuritySchemeType.ApiKey,
            Scheme = "Bearer",
            BearerFormat = "JWT",
            In = ParameterLocation.Header,
            Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer xxxxxxxxxxxxxxx\"",
        });
        options.AddSecurityRequirement(new OpenApiSecurityRequirement
        {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    }
                },
                new string[] {}
            }
        });
    })
    .AddFluentValidationAutoValidation().AddFluentValidationClientsideAdapters()
    .AddEventBus(eventBusBuilder =>
    {
        eventBusBuilder.UseMiddleware(typeof(ValidatorMiddleware<>));
        eventBusBuilder.UseMiddleware(typeof(LogMiddleware<>));
    })
    .AddServices(builder);

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseHttpsRedirection();

app.Run();

添加EFCore迁移依赖

		<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.15">
		  <PrivateAssets>all</PrivateAssets>
		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>
		<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.15">
		  <PrivateAssets>all</PrivateAssets>
		  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
		</PackageReference>


程序包管理器控制台
中输入
Add-Migration Init
生成
Init
的迁移文件(如果出现
error NETSDK1082: Microsoft.AspNetCore.App 没有运行时包可用于指定的 RuntimeIdentifier“browser-wasm”
这个错误的话就先把
TokenDemo.Admin.WebAssembly
项目移除)

使用
Update-Database
生成
Sqlitem

然后就可以看到项目中生成了
Catalog.db
文件

启动
TokenDemo.Service.Order
我们就可以看到Swagger的界面了

如何对接接口

打开
TokenDemo.Caller
项目中的``Callers\OrderCaller.cs`文件

修改
BaseAdderss

TokenDemo.Service.Order
的服务地址

打开
TokenDemo.Service.Order
项目的
Services\OrderService.cs
文件并且修改代码

namespace TokenDemo.Service.Services;

public class OrderService : ServiceBase
{
    public OrderService(IServiceCollection services) : base(services)
    {
        App.MapGet("/order/list", QueryList).Produces<List<Infrastructure.Entities.Order>>()
            .WithName("GetOrders");
    }

    public async Task<IResult> QueryList(IEventBus eventBus)
    {
        var orderQueryEvent = new QueryOrderListEvent();
        await eventBus.PublishAsync(orderQueryEvent);
        return Results.Ok(orderQueryEvent.Orders);
    }
}

然后在通过命令行启动
TokenDemo.Service.Order
项目

打开
TokenDemo\Admin
项目的
Pages\Home\Index.razor
文件并且修改代码

@page "/"
@using TokenDemo.Caller.Callers
@inherits LayoutComponentBase
@inject NavigationManager Nav
@inject OrderCaller OrderCaller
@code {

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        Nav.NavigateTo(GlobalVariables.DefaultRoute,true);
        var data = await OrderCaller.GetListAsync();
        await base.OnAfterRenderAsync(firstRender);
    }

}

并且在
await base.OnAfterRenderAsync(firstRender);
这里打一个断点用于查看是否获取到消息

打开
TokenDemo.Admin.Server
项目的
Program.cs
,添加以下代码

builder.Services.AddCaller(typeof(TokenDemo.Caller.Callers.OrderCaller).Assembly);

然后启动
TokenDemo.Admin.Server
项目,进入断点

得到结果

结尾

通过上文我们可以基本将
MasaFramework
的使用掌握,前端和后端的接口也掌握了

当前是
MasaFramework
的第三篇入门,我会继续学习
MasaFramework
并且分享给大家

来自token的分享

MASA Framework

学习交流:737776595

@

准备工作

  1. 安装python3环境
  2. 申请一个可用的语音转换API,此篇以
    Microsoft Azure Speech
    为例
    在Microsoft Azure 市场中搜索
    speech
    关键字找到语音服务。并创建好服务实例
    在这里插入图片描述
    在资源中找到创建的服务并查看
    在这里插入图片描述
    在此处点击显示密钥,我们要记住
    key
    值和
    location
    值,作为语音识别库的请求参数
    在这里插入图片描述

视频转音频

安装视频库
moviepy

pip install moviepy 

编写代码,将视频文件test.mp4中的音频提取到test2.wav

import moviepy.editor

videoClip = moviepy.editor.VideoFileClip(r"{}".format("test.mp4"))
videoClip.audio.write_audiofile(r"{}".format("test2.wav"))

识别音频到文本

安装语音识别库
SpeechRecognition

pip install SpeechRecognition 

编写代码,将视频文件
test3.wav
中的音频识别,并转换成文本写入
test.txt

import speech_recognition 

audio2 = speech_recognition.AudioFile("{}".format("test3.wav"))
recognizer =  speech_recognition.Recognizer()
with audio2 as source:
    audioData = recognizer.record(source)
result = recognizer.recognize_azure(audioData,key="<your api key>",language="zh-CN",location="eastus")
with open('test.txt', 'w') as file:
    if result.__len__()>0:
        file.write(result[0])

完整代码如下

import speech_recognition 
import moviepy.editor

videoClip = moviepy.editor.VideoFileClip(r"{}".format("test.mp4"))
videoClip.audio.write_audiofile(r"{}".format("test2.wav"))
audio2 = speech_recognition.AudioFile("{}".format("test2.wav"))
recognizer =  speech_recognition.Recognizer()
with audio2 as source:
    audioData = recognizer.record(source)
result = recognizer.recognize_azure(audioData,key="<your api key>",language="zh-CN",location="eastus")
with open('test.txt', 'w') as file:
    if result.__len__()>0:
        file.write(result[0])

音频直接转换文本

Azure提供了快捷转换语音到文本的工具
https://speech.microsoft.com/portal
点击实时语音转文本
在这里插入图片描述
这里需要注意的是,需要上传的音频格式为16kHz 或 8kHz、16 位和单声道 PCM
在这里插入图片描述
上传完成后将自动转换成文本
在这里插入图片描述

安装音频转换库
pydub

pip install pydub

编写代码,将
test.aac
文件以16kHz 采样率和单声道 PCM 编码方式,保存至
test1.wav
注意,如果使用ffmpeg编码的格式,需要下载ffmpeg相关库到脚本所在目录
http://www.ffmpeg.org/download.html#build-windows

from pydub import AudioSegment

audio1 = AudioSegment.from_file("test.aac", "aac")
#  -ac 1 -ar 16000 
audio1.export("test1.wav", format="wav",parameters=["-ac", "1", "-ar", "16000"])

前言

性能测试
是一个全栈工程师/架构师必会的技能之一,只有学会性能测试,才能根据得到的测试报告进行分析,找到系统性能的瓶颈所在,而这也是优化架构设计中重要的依据。

测试流程:

  1. 需求分析→环境搭建→测试计划→脚本开发→执行与监控→缺陷管理→结果与报告
    压力测试
  • 1、线程组设置,这里的线程数与同步定时器的用户数量一样
  • 2、添加HTTP cookie管理器
  • 3、默认请求值
  • 4、添加一个事务控制器,可以当作一个业务
  • 5、在事务控制器下添加,
    同步定时器
  • 设置用户数量,这里与线程组的线程数一样,超时时间可设置
  • 6、添加脚本(http请求)
  • 7、添加查看结果树
  • 8、添加->监听器
  • 9、在最后添加一个聚合报告,添加处:添加->监听器
  1. 负载测试实战
  • 1、线程组的
    设置50个用户
    (持续时间:按秒计算,这里300=60*5,意思就是运行时长为5分钟)
  • 2、添加HTTP cookie管理器
  • 3、默认请求值
  • 4、添加一个
    事务控制器,可以当作一个业务
  • 5、在事务控制器下添加,
    高斯随机定时器
  • 总的延时 = 固定延迟时间 + 高斯随机生成的偏差值(说明:单位都是毫秒,固定延迟300ms,偏差100ms,意思是时间延迟300-400ms之间)
  • 6、添加脚本(http请求)
  • 7、添加->监听器
  • 8、在最后添加一个
    聚合报告
    ,添加处:添加->监听器

第一章 Bug引发的又一次思考

1. 打开一个页面非常慢是Bug吗

  1. 打开一个页面非常慢是Bug吗
  • 可能是,原因:网络慢、客户端运算能力不足、资源大到现有的网络无法承载、服务端资源响应时间过长。
  1. 页面打开慢的影响是什么?
  • 用户体验不好,从而导致用户流失
  • 用户流失会导致项目失败
  • 项目失败可能会导致公司破产

2. 页面响应耗时可以提前预知吗?

  1. 在测试阶段是否能够发现页面响应慢

    当然可以

  2. 如何在测试阶段发现页面响应慢?

  • 模拟大量用户访问
  • 监控每个请求的响应是否准确
  • 监控服务器的资源使用

第2章 性能测试认知

1. 企业级软件为什么要做性能测试

  1. 历史上由于性能问题引发的事件
  • 12306网站崩溃,用户购票失败
  • 淘宝双十一网站崩溃
  1. 网站崩溃或慢对用户的影响
  • 离开
  1. 企业为什么要做性能测试?
  • 提升用户体验
  1. 细化性能测试的目的
  • 预估软件性能瓶顶,预估软件优化时间
  • 验证是否存在多并发的逻辑问题

2. 什么是性能测试?

1675939885447.png

  • 性能是用来描述产品除功能外的所具有的速度,效率和能力的综合能力评价

  • 对产品或是物品的性能惊喜定性或是定量的量测过程

  • 在这个过程中我们使用一些工具来进行场景的模拟,从而进行性能测试

3. 性能测试案例

  1. 测试需求:测试20个用户访问网站在负载达到30QPS时的平均响应时间
  2. QPS:Query Per Second 每秒查询率。(一台查询服务器每秒能够处理的查询次数,作为域名服务器的性能经常用每秒查询率来衡量)
  3. 测试步骤
  • 1、添加线程组(线程数+准备时长+循环次数)
  • 1.1、线程数:虚拟用户数,一个虚拟用户占用一个进程或线程(设置多少个虚拟用户=设置多少个线程)
  • 1.2、准备时长(s):设置的虚拟用户数需要多长时间全部启动。eg:线程数为20,准备时长为10,则说明需要10秒钟启动20个进程。
  • 1.3、循环次数:每个线程发送请求的次数。eg:线程数为20,循环次数为5,那么每个线程发送5次请求,总请求数为20*5=100

image.png

  • 2、添加HTTP请求

image.png

image.png

  • 3、设置QPS限制:控制给定的取样器发送请求的吞吐量

image.png

image.png

  • 4、添加监视器-聚合报告、察看结果树

image.png

image.png

image.png

  • 5、运行脚本

image.png

  • 6、聚合报告解析(响应时间单位:毫秒)
  • 1)Label:每个Jmeter的element都有一个Name属性,这里显示的就是Name属性的值
  • 2)#Sample:表示你这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100
  • 3)Average:平均响应时间-默认情况下是单个Request的平均响应时间当使用了Transaction Controller 时,也可以以Transaction为单位显示平均响应时间
  • 4)Median:中位数,50%用户的响应时间
  • 5)90%Line:90%用户响应时间
  • 6)Min:最小响应时间
  • 7)Max:最大响应时间
  • 8)Error%:本次测试中出现错误的请求的数量/请求的总数
  • 9)Throughput:吞吐量-默认情况下白石每秒的请求数
  • 10)KB/sec:每秒从服务器端接收到的数据量

image.png

image.png

4. 性能测试的分类

  1. 性能测试的分类
  • 压力测试、负载测试、并发测试、稳定性测试
  1. 什么是压力测试?
  • 压力测试也叫强度测试,它是指逐步给系统增加压力,测试系统的性能变化,使系统某些资源达到饱和或系统崩溃的边缘,从而确定系统所能承受的最大压力
  • 举个例子:百米赛跑,逐步增加你的负重,直到你完不成百米的程度,也就是崩溃的边缘你所能承受的最大负重
  1. 什么是负载测试?
  • 被测试系统正常服务的前提下,系统所能承担的最大服务负荷数量(即最大并发数量),最终分析出系统性能的瓶颈
  • 举个例子:百米赛跑,设置必须15秒完成,负重奔跑(不断增加负重)
  1. 压力测试和负载测试的区别
  • 压力测试要测试出系统即将崩溃时,能够承受的最大并发数
  • 负载测试是满足系统指标要求的情况下,能够承受的最大并发数
  1. 什么是并发测试
  • 举个例子:商场卖货,售后员根据库存表单记录表卖货
  • 仓库管理员应该在出货时同时更新库存表单记录表,但由于用户过多,表单记录更新不及时
  • 导致仓库已经没有货了,但是售货员看到库存表单记录表中还显示有库存,仍然在卖货,但已经发不出去货了

5. 性能测试场景剖析

  • 电商秒杀、学习系统考试、12306抢票、新闻热点事件、
    网络游戏运营、视频网站播放

6. 必知必会的性能测试指标

  • 并发用户量:同一单位时间进行同一操作的用户数量
  • 吞吐量:单位时间内系统成功传输的数据量,单位通常是MB、GB
  • 吞吐率:又叫Throughput,单位时间内系统成功处理的请求数量,通常单位为(请求数量/每秒、req/s)

7. 性能测试基本流程

  1. 标准性能测试流程
    1675943449153.png

8.
简述 性能测试流程?

1.分析性能需求。挑选用户使用最频繁的场景来测试,比如:登陆,搜索,下单等等。确定性能指标,比如:事务通过率为100%,TOP99%是5秒,最大并发用户为1000人,CPU和内存的使用率在70%以下

2.制定性能测试计划,明确测试时间(通常在功能稳定后,如第一轮测试后进行)和测试环境和测试工具

3.编写测试用例

4.搭建测试环境,准备好测试数据

5.编写性能测试脚本

6.性能测试脚本调优。设置检查点、参数化、关联、集合点、事务,调整思考时间,删除冗余脚本

7.设计测试场景,运行测试脚本,监控服务器,

8.分析测试结果,收集相关的日志提单给开发

9.回归性能测试

10.编写测试报告