捆绑 / artilleryphp
Artillery.io的PHP包装器。
Requires
- php: ^8.1
- symfony/yaml: ^5.0
This package is auto-updated.
Last update: 2024-09-05 21:09:00 UTC
README
Artillery.io是一个现代、强大且易于使用的性能测试工具包。
ArtilleryPhp是一个用于在PHP8中编写和维护Artillery脚本的库。
文档包含
- 每个类和方法的完整解释。
- 每个类和大多数方法的示例代码。
- 链接到Artillery参考文档的每个部分。
目录
安装
您可以通过Composer安装此库。
composer require bundeling/artilleryphp
此库需要symfony/yaml
包以将其内部数组渲染为YAML格式。
用法
此示例位于examples/artilleryphp-usage。
步骤1:创建一个新的Artillery实例
您可以使用Artillery::new($target)
获取一个新实例,并使用流畅的接口设置配置值
use ArtilleryPhp\Artillery; $artillery = Artillery::new('https://:3000') ->addPhase(['duration' => 60, 'arrivalRate' => 5, 'rampTo' => 20], 'Warm up') ->addPhase(['duration' => 60, 'arrivalRate' => 20], 'Sustain') ->setPlugin('expect') ->setEnvironment('live', ['target' => 'https://www.example.com']);
您也可以从完整的或部分数组表示形式创建一个
$artillery = Artillery::fromArray([ 'config' => [ 'target' => 'https://:3000', 'phases' => [ ['duration' => 60, 'arrivalRate' => 5, 'rampTo' => 20, 'name' => 'Warm up'], ['duration' => 60, 'arrivalRate' => 20, 'name' => 'Sustain'], ], 'plugins' => [ // To produce an empty object as "{ }", use stdClass. // This is automatic when using setPlugin(s), setEngine(s) and setJson(s). 'expect' => new stdClass(), ], 'environments' => [ 'live' => ['target' => 'https://www.example.com'] ] ] ]);
或从现有的YAML文件,或其他Artillery
实例
! 警告:目前对fromYaml
和merge
方法的支持不是很好;fromYaml主要与该库的输出兼容;如果第二级键已经定义(例如,尝试合并第二个环境),则merge将不执行任何操作。
$config = Artillery::fromYaml(__DIR__ . '/default-config.yml'); $environments = Artillery::fromYaml(__DIR__ . '/default-environments.yml'); // New instance from the config, and merging in environments from another file: $artillery = Artillery::from($config)->merge($environments);
步骤2:定义场景的流程并将其添加到Artillery实例中
// Create some requests: $loginRequest = Artillery::request('get', '/login') ->addCapture('token', 'json', '$.token') ->addExpect('statusCode', 200) ->addExpect('contentType', 'json') ->addExpect('hasProperty', 'token'); $inboxRequest = Artillery::request('get', '/inbox') ->setQueryString('token', '{{ token }}') ->addExpect('statusCode', 200); // Create a flow with the requests, and a 500ms delay between: $flow = Artillery::scenario() ->addRequest($loginRequest) ->addThink(0.5) ->addRequest($inboxRequest); // Let's loop the flow 10 times: $scenario = Artillery::scenario()->addLoop($flow, 10); // Add the scenario to the Artillery instance: $artillery->addScenario($scenario);
提示
存在复数版本以接受原始数组表示形式的多个条目
$loginRequest = Artillery::request('post', '/login') ->setQueryStrings([ 'username' => '{{ username }}', 'password' => '{{ password }}']) ->addCaptures([ ['json' => '$.token', 'as' => 'token'], ['json' => '$.id', 'as' => 'id']]);
注意set和add differentiation之间的区别,以及;
有关原始表示规范,请参阅Artillery参考文档。
步骤3:导出到YAML
// Without argument will build the YAML as the same name as the php file: $artillery->build(); // Maybe even run the script right away (assumes `npm install -g artillery`): $artillery->run();
这将生成以下readme-example.yml
文件
config: target: 'https://:3000' phases: - duration: 60 arrivalRate: 5 rampTo: 20 name: 'Warm up' - duration: 60 arrivalRate: 20 name: Sustain plugins: expect: { } scenarios: - flow: - loop: - get: url: /login capture: - json: $.token as: token expect: - statusCode: 200 - contentType: json - hasProperty: token - think: 0.5 - get: url: /inbox qs: token: '{{ token }}' expect: - statusCode: 200 count: 10
提示
对于非常基本的脚本,您也可以直接将请求(单个或数组)添加到Artillery实例中,以从中创建新的场景
$artillery = Artillery::new() ->addScenario(Artillery::request('get', 'http://www.google.com'));
注意
当前实现构建内部数组表示。这意味着对获取特定索引的Scenario
实例或取消设置属性的操作支持有限或没有支持。目前请考虑组合,并期待v2。
Artillery类
Artillery
类包含与Artillery脚本配置部分相关的所有方法,以及添加场景。
文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Artillery
对于自定义配置设置,有一个set(key: string, value: mixed)
函数可用。
目标
如果设置了目标,它将用作脚本中所有请求的基本URL。
您可以通过构造函数传递基本URL或使用Artillery实例上的setTarget
方法。您还可以完全跳过此步骤,并在每个请求中提供完全限定的URL。
// Base URL in the Scenario with relateve path in the request: $artillery = Artillery::new('https://:3000') ->addScenario(Artillery::request('get', '/home')); // Without target, and fully qualified URL in Request: $artillery = Artillery::new() ->addScenario(Artillery::request('get', 'https://:3000/home')); // Setting the target when initializing from another source: $file = __DIR__ . '/default-config.yml'; $default = Artillery::fromYaml($file) ->setTarget('http://www.example.com'); $artillery = Artillery::from($default) ->setTarget('https://:3000');
环境
可以使用配置覆盖来指定环境,例如目标URL和阶段。
您可以使用另一个Artillery实例的配置,或者使用配置值数组。
$local = Artillery::new('https://:8080') ->addPhase(['duration' => 30, 'arrivalRate' => 1, 'rampTo' => 10]) ->setHttpTimeout(60); $production = Artillery::new('https://example.com') ->addPhase(['duration' => 300, 'arrivalRate' => 10, 'rampTo' => 100]) ->setHttpTimeout(30); $artillery = Artillery::new() ->setEnvironment('staging', ['target' => 'https://staging.example.com']) ->setEnvironment('production', $production) ->setEnvironment('local', $local);
静态工厂辅助工具:使用这些来获取新实例并立即调用它们的方法
- Artillery:
new([targetUrl: null|string = null]): Artillery
- 场景:
scenario([name: null|string = null]): Scenario
- 请求:
request([method: null|string = null], [url: null|string = null]): Request
- Ws请求:
wsRequest([method: null|string = null], [request: mixed = null]): WsRequest
- 任意请求:
anyRequest([method: null|string = null], [request: mixed = null]): AnyRequest
$artillery = Artillery::new($targetUrl) ->addPhase(['duration' => 60, 'arrivalRate' => 10]); $request = Artillery::request('get', '/login') ->addCapture('token', 'json', '$.token'); $scenario = Artillery::scenario('Logging in')->addRequest($request);
场景相关方法
您可以添加一个完整构建的场景,或者传递单个请求或请求数组,然后从中创建一个场景。
请参阅场景类以获取更多详细信息。
addScenario(scenario: array|RequestInterface|RequestInterface[]|Scenario, [options: mixed[]|null = null])
- 将场景添加到Artillery脚本的场景部分。
setAfter(after: array|RequestInterface|RequestInterface[]|Scenario)
- 设置在场景部分中的场景完成后要运行的场景。
setBefore(before: array|RequestInterface|RequestInterface[]|Scenario)
- 添加一个场景,在场景部分的任何给定场景之前运行。
处理器 & 函数钩子
场景的流程和请求可以具有JavaScript函数钩子,可以读取和修改上下文,如变量。
以下是从examples/generating-vu-tokens的一个非常具有说明性的示例。
// This scenario will run once before any main scenarios/virtual users; here we're using a js function // from a processor to generate a variable available in all future scenarios and their virtual users: $before = Artillery::scenario()->addFunction('generateSharedToken'); // One of the main scenarios, which has access to the shared token, // and here we're generating a token unique to every main scenario that executed. $scenario = Artillery::scenario() ->addFunction('generateVUToken') ->addLog('VU id: {{ $uuid }}') ->addLog(' shared token is: {{ sharedToken }}') ->addLog(' VU-specific token is: {{ vuToken }}') ->addRequest( Artillery::request('get', '/') ->setHeaders([ 'x-auth-one' => '{{ sharedToken }}', 'x-auth-two' => '{{ vuToken }}' ])); $artillery = Artillery::new('http://www.artillery.io') ->setProcessor('./helpers.js') ->setBefore($before) ->addScenario($scenario);
以./helpers.js
为
module.exports = { generateSharedToken, generateVUToken }; function generateSharedToken(context, events, done) { context.vars.sharedToken = `shared-token-${Date.now()}`; return done(); } function generateVUToken(context, events, done) { context.vars.vuToken = `vu-token-${Date.now()}`; return done(); }
请参阅Artillery.io文档以获取必要的函数签名。
配置设置
请参阅文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Artillery#methods
addEnsureCondition(expression: string, [strict: bool|null = null])
addEnsureConditions(thresholds: array[])
addEnsureThreshold(metricName: string, value: int)
addEnsureThresholds(thresholds: int[][])
setEngine(name: string, [options: array|null = null])
setEngines(engines: array[]|string[])
setEnvironment(name: string, config: array|Artillery)
setEnvironments(environments: array[]|Artillery[])
addPayload(path: string, fields: array, [options: bool[]|string[] = [...]])
addPayloads(payloads: bool[][]|string[][])
addPhase(phase: array, [name: null|string = null])
addPhases(phases: array[])
setPlugin(name: string, [options: array|null = null])
setPlugins(plugins: array)
setVariable(name: string, value: mixed)
setVariables(variables: mixed[])
setHttp(key: string, value: bool|int|mixed)
setHttps(options: bool[]|int[])
setHttpTimeout(timeout: int)
setHttpMaxSockets(maxSockets: int)
setHttpExtendedMetrics([extendedMetrics: bool = true])
setProcessor(path: string)
setTarget(url: string)
setTls(rejectUnauthorized: bool)
setWs(wsOptions: array)
渲染和加载
build([file: null|string = null]): Artillery
构建脚本并将其保存为YAML文件。toYaml(): string
将脚本渲染为Yaml字符串。from(artillery: Artillery): Artillery
从给定的Artillery实例创建新的Artillery实例。fromArray(script: array): Artillery
从给定的数组数据创建新的Artillery实例。fromYaml(file: string): Artillery
从给定的Yaml文件创建新的Artillery实例。toArray(): array
获取当前Artillery实例的数组表示。run([reportFile: null|string = null], [debug: null|string = null]): Artillery
运行构建的脚本(或构建和运行),并将报告保存到带时间戳的文件中。
场景类
场景类包括与场景及其流程相关的所有方法。
文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Scenario
// Imagine we have an already defined Scenario as $defaultScenario $scenario = Artillery::scenario() ->setName('Request, pause 2 seconds, then default flow.') ->addRequest(Artillery::request('GET', '/')) ->addThink(2) ->addFlow($defaultScenario);
方法
文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Scenario#methods
自定义场景设置
set(key: string, value: mixed)
从另一个场景添加到当前场景的流程
addFlow(scenario: Scenario)
杂项
setName(name: string)
用于指标报告。setWeight(weight: int)
默认:1。确定与其他场景相比,此场景被选中的概率。
如果没有设置,引擎默认为HTTP请求。要创建WebSocket场景,需要指定此场景的引擎为'ws',并仅使用WsRequest
类的实例,这些实例在Artillery::wsRequest()
中可用。
setEngine(engine: string)
场景级别的JavaScript函数钩子,来自在Artillery
实例中定义的setProcessor
中的Js文件
addAfterScenario(function: array|string|string[])
addBeforeScenario(function: array|string|string[])
对于请求,同样有场景级别的在请求前后的钩子
addAfterResponse(function: array|string|string[])
addBeforeRequest(function: array|string|string[])
有关js函数钩子的更多详细信息,请参阅Artillery.io 文档
流程方法
addRequest(request: RequestInterface)
addRequests(requests: RequestInterface[])
addLoop(loop: array|RequestInterface|RequestInterface[]|Scenario|Scenario[], [count: int|null = null], [over: null|string = null], [whileTrue: null|string = null])
addLog(message: string, [ifTrue: null|string = null])
addThink(duration: float, [ifTrue: null|string = null])
addFunction(function: array|string|string[], [ifTrue: null|string = null])
请求类
文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Request
Request
类包含与HTTP请求相关的所有方法,以及从RequestBase
类继承的一些共享方法。
$getTarget = Artillery::request('get', '/inbox') ->setJson('client_id', '{{ id }}') ->addCapture('first_inbox_id', 'json', '$[0].id'); $postResponse = Artillery::request('post', '/inbox') ->setJsons(['user_id' => '{{ first_inbox_id }}', 'message' => 'Hello, world!']);
对于WebSocket,可以在Artillery::wsRequest()
中找到WsRequest
类的粗略实现。
$stringScenario = Artillery::scenario('Sending a string') ->setEngine('ws') ->addRequest(Artillery::wsRequest('send', 'Artillery'));
对于自定义请求,AnyRequest
应与这些函数匿名使用。
set(key: string, value: mixed)
setMethod(method: string)
setRequest(request: mixed)
$emitAndValidateResponse = Artillery::scenario('Emit and validate response') ->setEngine('socketio') ->addRequest( Artillery::anyRequest('emit') ->set('channel', 'echo') ->set('data', 'Hello from Artillery') ->set('response', ['channel' => 'echoResponse', 'data' => 'Hello from Artillery']));
方法
请参阅文档:https://bundeling.github.io/ArtilleryPhp/classes/ArtilleryPhp-Request#methods
addAfterResponse(function: array|string|string[])
addBeforeRequest(function: array|string|string[])
setAuth(user: string, pass: string)
setBody(body: mixed)
setCookie(name: string, value: string)
setCookies(cookies: string[])
setFollowRedirect([followRedirect: bool = true])
setForm(key: string, value: mixed)
setForms(form: array)
setFormDatas(formData: array)
setFormData(key: string, value: mixed)
setGzip([gzip: bool = true])
setHeader(key: string, value: string)
setHeaders(headers: string[])
setIfTrue(expression: string)
setJson([key: null|string = null], [value: mixed = null])
setJsons(jsons: mixed[])
setMethod(method: string)
setQueryStrings(key: string, value: mixed)
setQueryStrings(qs: array)
setUrl(url: string)
继承
set(key: string, data: mixed)
setMethod(method: string)
setRequest(request: mixed)
addCapture(as: string, type: string, expression: string, [strict: bool = true], [attr: null|string = null], [index: int|null|string = null])
addCaptures(captures: int[][]|string[][])
addExpect(type: string, value: mixed, [equals: mixed = null])
addExpects(expects: mixed[][])
addMatch(type: string, expression: string, value: mixed, [strict: bool = true], [attr: null|string = null], [index: int|null|string = null])
addMatches(matches: mixed[][])