NBomber.FSharp
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 |  |

Scenario
| 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
}
|
Step
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
}
|
Client factory
Simplified construction of clients. Notable differences are:
connect and disconnect functions are more tolerant for missing type signatures and arguments
- no need for
cancellationToken argument if it is not used in connect or disconnect functions
disconnect can be omitted completely, if the type of created connection implements IDisposable or can be just disposed.
count of connections can be omitted too, it defaults to 1
- 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))
}
|
Reporter
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
...
}
|
Other runner configuration
| 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
}
|