Skip to content

Commit

Permalink
added NBomberRunner.withTargetScenarios and --target CLI args
Browse files Browse the repository at this point in the history
  • Loading branch information
AntyaDev committed Apr 2, 2022
1 parent 77911da commit 8caddac
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 31 deletions.
5 changes: 5 additions & 0 deletions src/NBomber/Api/CSharp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ type NBomberRunner =
static member RegisterScenarios([<ParamArray>]scenarios: Scenario[]) =
scenarios |> Seq.toList |> FSharp.NBomberRunner.registerScenarios

/// Sets target scenarios among all registered that will execute
static member WithTargetScenarios(context: NBomberContext, [<ParamArray>]scenarioNames: string[]) =
let names = scenarioNames |> Seq.toList
context |> FSharp.NBomberRunner.withTargetScenarios(names)

/// Sets test suite name
/// Default value is: nbomber_default_test_suite_name.
[<Extension>]
Expand Down
42 changes: 28 additions & 14 deletions src/NBomber/Api/FSharp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ module NBomberRunner =
let registerScenarios (scenarios: Contracts.Scenario list) =
{ NBomberContext.empty with RegisteredScenarios = scenarios }

/// Sets target scenarios among all registered that will execute
let withTargetScenarios (scenarioNames: string list) (context: NBomberContext) =
context |> NBomberContext.setTargetScenarios scenarioNames

/// Sets test suite name
/// Default value is: nbomber_default_test_suite_name.
let withTestSuite (testSuite: string) (context: NBomberContext) =
Expand Down Expand Up @@ -320,33 +324,43 @@ module NBomberRunner =
{ context with UseHintsAnalyzer = false }

let internal executeCliArgs (args) (context: NBomberContext) =
let invokeConfigLoader (configName) (configLoader) (config) (context) =
if config = String.Empty then $"{configName} is empty" |> failwith
elif String.IsNullOrEmpty config then context
else configLoader config context

let loadConfigFn (loadConfig) (configPath) (context) =
if String.IsNullOrWhiteSpace configPath then context
else loadConfig configPath context

let setTargetScenarios (targetScenarios: string seq) (context: NBomberContext) =
if Seq.isEmpty targetScenarios then context
else NBomberContext.setTargetScenarios (List.ofSeq targetScenarios) context

match CommandLine.Parser.Default.ParseArguments<CommandLineArgs>(args) with
| :? Parsed<CommandLineArgs> as parsed ->
let values = parsed.Value
let execLoadConfigCmd = invokeConfigLoader "config" loadConfig values.Config
let execLoadInfraConfigCmd = invokeConfigLoader "infra config" loadInfraConfig values.InfraConfig
let execCmd = execLoadConfigCmd >> execLoadInfraConfigCmd
let cliArgs = parsed.Value
let loadCnf = loadConfigFn loadConfig cliArgs.Config
let loadInfra = loadConfigFn loadInfraConfig cliArgs.InfraConfig

context |> execCmd
let run =
loadCnf
>> loadInfra
>> setTargetScenarios cliArgs.TargetScenarios

run context

| _ -> context

let internal runWithResult (args) (context: NBomberContext) =
GCSettings.LatencyMode <- GCLatencyMode.SustainedLowLatency
context
|> executeCliArgs args
|> NBomberRunner.run

if Seq.isEmpty args then
NBomberRunner.run context
else
context |> executeCliArgs args |> NBomberRunner.run

let run (context: NBomberContext) =
context
|> runWithResult List.empty
|> Result.map(fun x -> x.FinalStats)
|> Result.mapError(AppError.toString)
|> Result.mapError AppError.toString

/// Runs scenarios with arguments.
/// The following CLI commands are supported:
Expand All @@ -359,4 +373,4 @@ module NBomberRunner =
context
|> runWithResult args
|> Result.map(fun x -> x.FinalStats)
|> Result.mapError(AppError.toString)
|> Result.mapError AppError.toString
3 changes: 3 additions & 0 deletions src/NBomber/Contracts.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type NBomberContext = {
Reporting: ReportingContext
WorkerPlugins: IWorkerPlugin list
UseHintsAnalyzer: bool
TargetScenarios: string list option
} with

[<CompiledName("Empty")>]
Expand All @@ -46,6 +47,7 @@ type NBomberContext = {
}
WorkerPlugins = List.empty
UseHintsAnalyzer = true
TargetScenarios = None
}

namespace NBomber.Contracts.Internal
Expand All @@ -56,6 +58,7 @@ open NBomber.Contracts
type CommandLineArgs = {
[<Option('c', "config", HelpText = "NBomber configuration")>] Config: string
[<Option('i', "infra", HelpText = "NBomber infra configuration")>] InfraConfig: string
[<Option('t', "target", HelpText = "Target Scenarios")>] TargetScenarios: string seq
}

type StepResponse = {
Expand Down
9 changes: 7 additions & 2 deletions src/NBomber/DomainServices/NBomberContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,17 @@ let getScenariosSettings (scenarios: DomainTypes.Scenario list) (context: NBombe

let getTargetScenarios (context: NBomberContext) =
let targetScn =
context.NBomberConfig
|> Option.bind(fun x -> x.TargetScenarios)
context.TargetScenarios
|> Option.orElseWith(fun () ->
context.NBomberConfig |> Option.bind(fun x -> x.TargetScenarios)
)

let allScns = context.RegisteredScenarios |> List.map(fun x -> x.ScenarioName)
defaultArg targetScn allScns

let setTargetScenarios (scenarios: string list) (context: NBomberContext) =
{ context with TargetScenarios = Some scenarios }

let getReportFileName (context: NBomberContext) =
let tryGetFromConfig (ctx) = option {
let! config = ctx.NBomberConfig
Expand Down
24 changes: 9 additions & 15 deletions tests/NBomber.IntegrationTests/CliArgsTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ let okStep = Step.create("ok step", fun _ -> task {
})

let scenario = Scenario.create "scenario" [okStep] |> Scenario.withoutWarmUp
let scenario2 = Scenario.create "scenario2" [okStep] |> Scenario.withoutWarmUp

[<Theory>]
[<InlineData("-c")>]
Expand Down Expand Up @@ -87,19 +88,12 @@ let ``CLI commands should throw ex if infra config file is not found`` (command)
|> ignore)

[<Theory>]
[<InlineData("-c")>]
[<InlineData("--config")>]
let ``CLI commands should throw ex if config file is empty`` (command) =
Assert.Throws(typeof<Exception>,
fun _ -> NBomberRunner.registerScenarios [scenario]
|> NBomberRunner.executeCliArgs [command; ""]
|> ignore)
[<InlineData("-t")>]
[<InlineData("--target")>]
let ``TargetScenarios should update NBomberContext`` (command) =
let context =
NBomberRunner.registerScenarios [scenario; scenario2]
|> NBomberRunner.executeCliArgs [command; "scenario2"]

[<Theory>]
[<InlineData("-i")>]
[<InlineData("--infra")>]
let ``CLI commands should throw ex if infra config file is empty`` (command) =
Assert.Throws(typeof<Exception>,
fun _ -> NBomberRunner.registerScenarios [scenario]
|> NBomberRunner.executeCliArgs [command; ""]
|> ignore)
test <@ context.TargetScenarios.Value.Length = 1 @>
test <@ context.TargetScenarios.Value.Head = "scenario2" @>
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Compile Include="HintsAnalyzerTests.fs" />
<Compile Include="NBomberRunnerTests.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
Expand Down
1 change: 1 addition & 0 deletions tests/NBomber.IntegrationTests/NBomberContextTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ let context = {
}
WorkerPlugins = List.empty
UseHintsAnalyzer = false
TargetScenarios = None
}

[<Fact>]
Expand Down
39 changes: 39 additions & 0 deletions tests/NBomber.IntegrationTests/NBomberRunnerTests.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module Tests.NBomberRunner

open System.Threading.Tasks
open Xunit
open Swensen.Unquote

open NBomber
open NBomber.Contracts
open NBomber.FSharp
open NBomber.Domain

[<Fact>]
let ``withTargetScenarios should run only specified scenarios`` () =

let mutable scn1Started = false
let mutable scn2Started = false

let okStep = Step.create("ok step", fun ctx -> task {
do! Task.Delay(milliseconds 100)
return Response.ok()
})

let scn1 =
Scenario.create "scn_1" [okStep]
|> Scenario.withInit(fun _ -> task { scn1Started <- true })
|> Scenario.withLoadSimulations [KeepConstant(1, seconds 1)]

let scn2 =
Scenario.create "scn_2" [okStep]
|> Scenario.withInit(fun _ -> task { scn2Started <- true })
|> Scenario.withLoadSimulations [KeepConstant(1, seconds 1)]

NBomberRunner.registerScenarios [scn1; scn2]
|> NBomberRunner.withTargetScenarios ["scn_2"]
|> NBomberRunner.run
|> ignore

test <@ scn1Started = false @>
test <@ scn2Started @>

0 comments on commit 8caddac

Please sign in to comment.