F# Computation Expressions for NBomber API
Package | Description | Status |
---|---|---|
NBomber.FSharp | CE for test runners, scenarios and steps | |
NBomber.FSharp.Http | CE for http calls steps, similar to NBomber.Plugins.Http | |
NBomber.FSharp.Hopac | Hopac support for the above, depends on both |
Fluent API | Computation Expression |
---|---|
Scenario.create "test" [step]
|> Scenario.withWarmUp (seconds 10)
|> Scenario.withLoadSimulations [
KeepConstant(copies = copiesCount, during = seconds 2)
] |
scenario "test" {
warmUp (seconds 10)
load [
KeepConstant(copies = copiesCount, during = seconds 2)
]
init (fun _ -> Task.FromResult())
clean (fun _ -> Task.FromResult())
steps [myStep]
// or if just one step
myStep
} |
The overloads of step
's custom operation execute
accepts a function taking a step context and returning either Response
or unit
directly or wrapped in a task
, async
or even in a Hopac job
Fluent API | Computation Expression |
---|---|
Step.create("step name",
myWebsocketPool,
myGuidFeed,
(fun ctx -> task {
let doSomethingWithSocket (_: Guid) (_: ClientWebSocket) =
""
ctx.Logger.Information("Can take feed and client {Ret}",
takeBoth ctx.FeedItem ctx.Client)
return Response.Ok()
}), true)
|
step "step name" {
dataFeed myGuidFeed
myWebsocketPool
execute (fun ctx ->
let doSomethingWithSocket (_: Guid) (_: ClientWebSocket) =
""
ctx.Logger.Information("Can take feed and client {Ret}",
takeBoth ctx.FeedItem ctx.Client) )
doNotTrack
} |
Simplified construction of clients. Notable differences are:
connect
anddisconnect
functions are more tolerant for missing type signatures and arguments- no need for
cancellationToken
argument if it is not used inconnect
ordisconnect
functions disconnect
can be omitted completely, if the type of created connection implementsIDisposable
or can be just disposed.count
of connections can be omitted too, it defaults to1
- even less verbose compared to the C# API
Fluent API | Computation Expression |
---|---|
let clientFactory =
ClientFactory.create(
name = "db connections",
initClient = (fun i ctx -> task {
let c = new NpgsqlConnection(connectionString)
do! c.OpenAsync(ctx.CancellationToken)
return c
}),
disposeClient = (fun (c:NpgsqlConnection, ctx) -> c.CloseAsync(ctx.CancellationToken)),
clientCount = 100)
|
let clientFactory =
clients "db connections" {
count 100
connect(fun i ctx -> task {
let c = new NpgsqlConnection(connectionString)
do! c.OpenAsync(ctx.CancellationToken)
return c
})
disconnect(fun c ctx -> c.CloseAsync(ctx.CancellationToken))
} |
Imagine you need just a html report. Then it is as short as
report { html }
Fluent API | Computation Expression |
---|---|
NBomberRunner.withReportFormats [
ReportFormat.Csv
ReportFormat.Txt
ReportFormat.Md
ReportFormat.Html
]
|> NBomberRunner.withReportingSinks
[ influxdbSink
customFormatSink ]
(seconds 10)
|> NBomberRunner.withReportFolder "reportsFolder"
|> NBomberRunner.withReportFileName "reportFile"
// or if none
|> NBomberRunner.withoutReports
...
|
testSuite "Suite name" {
report {
csv
text
markdown
html
sink influxdbSink
sink customFormatSink
interval (seconds 10)
folderName "reportsFolder"
fileName "reportFile"
}
// or if none
noReports
...
}
|
Fluent API | Computation Expression |
---|---|
NBomberRunner.registerScenarios []
|> NBomberRunner.withTestName "Test name"
|> NBomberRunner.withTestSuite "Suite name"
|> NBomberRunner.withoutReports
|> NBomberRunner.disableHintsAnalyzer
|> NBomberRunner.loadConfig "loadTestConfig.json"
|> NBomberRunner.loadInfraConfig "infrastructureConfig.json"
|> NBomberRunner.withWorkerPlugins []
|> NBomberRunner.withApplicationType ApplicationType.Console
// |> NBomberRunner.runWithArgs args
|> NBomberRunner.run
|> evaluateStatsFunction |
testSuite "Suite name" {
testName "Test name"
noReports
noHintsAnalyzer
scenarios scenarioBuilderTest
config "loadTestConfig.json"
infraConfig "infrastructureConfig.json"
plugins [ (* plugins list*) ]
runConsole
// runAsProcess
// runWithArgs args
// runWithExitCode
} |