Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

console work #258

Merged
merged 10 commits into from
Jul 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Expecto.Tests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1300,7 +1300,7 @@ let cancel =
use ct = new CancellationTokenSource()
let! _ = Async.StartChild(async { do! Async.Sleep 50
ct.Cancel() })
let! results = evalTestsWithCancel ct.Token config t
let! results = evalTestsWithCancel ct.Token config t false
results |> List.iter (fun (_,r) ->
let d = int r.duration.TotalMilliseconds
Expect.isLessThan d 1000 "cancel length"
Expand Down
2 changes: 1 addition & 1 deletion Expecto/Expect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ let streamsEqual (s1 : IO.Stream) (s2 : IO.Stream) message =
/// subset of the functions. Statistical test to 99.99% confidence level.
let isFasterThanSub (f1:Performance.Measurer<_,_>->'a) (f2:Performance.Measurer<_,_>->'a) format =
let toString (s:SampleStatistics) =
sprintf "%.4f \u00B1 %.4f ms" s.mean s.meanStandardError
sprintf "%.4f ± %.4f ms" s.mean s.meanStandardError

match Performance.timeCompare f1 f2 with
| Performance.ResultNotTheSame (r1, r2)->
Expand Down
126 changes: 81 additions & 45 deletions Expecto/Expecto.fs
Original file line number Diff line number Diff line change
Expand Up @@ -619,33 +619,29 @@ module Impl =
>> setField "reason" m)

failed = fun n m d ->
logger.logWithAck LogLevel.Error (
eventX "{testName} failed in {duration}. {message}"
>> setField "testName" n
>> setField "duration" d
>> setField "message" m)
async {
do! logger.logWithAck LogLevel.Error (
eventX "{testName} failed in {duration}. {message}"
>> setField "testName" n
>> setField "duration" d
>> setField "message" m)
ANSIOutputWriter.Flush()
}

exn = fun n e d ->
logger.logWithAck LogLevel.Error (
eventX "{testName} errored in {duration}"
>> setField "testName" n
>> setField "duration" d
>> addExn e)
async {
do! logger.logWithAck LogLevel.Error (
eventX "{testName} errored in {duration}"
>> setField "testName" n
>> setField "duration" d
>> addExn e)
ANSIOutputWriter.Flush()
}


summary = fun config summary ->
summary = fun _config summary ->
let spirit =
if summary.successful then
if Console.OutputEncoding.WebName = "utf-8"
&& not config.mySpiritIsWeak then
"ᕙ໒( ˵ ಠ ╭͜ʖ╮ ಠೃ ˵ )७ᕗ"
else
"Success!"
else
if Console.OutputEncoding.WebName = "utf-8"
&& not config.mySpiritIsWeak then
"( ರ Ĺ̯ ರೃ )"
else
""
if summary.successful then "Success!" else String.Empty
let commonAncestor =
let rec loop ancestor (descendants : string list) =
match descendants with
Expand Down Expand Up @@ -852,7 +848,7 @@ module Impl =
/// FsCheck end size (default: 100 for testing and 10,000 for
/// stress testing).
fsCheckEndSize: int option
/// Turn off spirits.
/// Depricated. Will be removed on next major release.
mySpiritIsWeak: bool
/// Allows duplicate test names.
allowDuplicateNames: bool
Expand All @@ -866,10 +862,11 @@ module Impl =
filter = id
failOnFocusedTests = false
printer =
if Environment.GetEnvironmentVariable "TEAMCITY_PROJECT_NAME" <> null then
TestPrinters.teamCityPrinter TestPrinters.defaultPrinter
else
let tc = Environment.GetEnvironmentVariable "TEAMCITY_PROJECT_NAME"
if isNull tc then
TestPrinters.defaultPrinter
else
TestPrinters.teamCityPrinter TestPrinters.defaultPrinter
verbosity = Info
logName = None
locate = fun _ -> SourceLocation.empty
Expand Down Expand Up @@ -953,9 +950,14 @@ module Impl =
config.parallelWorkers

/// Evaluates tests.
let evalTestsWithCancel (ct:CancellationToken) config test =
let evalTestsWithCancel (ct:CancellationToken) config test progressStarted =
async {

let tests = Test.toTestCodeList test
let testLength = List.length tests

let testsCompleted = ref 0

let evalTestAsync (test:FlatTest) =

let beforeEach (test:FlatTest) =
Expand All @@ -966,10 +968,14 @@ module Impl =
let! result = execTestAsync ct config test
do! beforeAsync
do! TestPrinters.printResult config test result

if progressStarted then
Fraction (Interlocked.Increment testsCompleted, testLength)
|> ProgressIndicator.update

return test,result
}

let tests = Test.toTestCodeList test
let inline cons xs x = x::xs

if not config.``parallel`` ||
Expand Down Expand Up @@ -1015,7 +1021,7 @@ module Impl =

/// Evaluates tests.
let evalTests config test =
evalTestsWithCancel CancellationToken.None config test
evalTestsWithCancel CancellationToken.None config test false

let evalTestsSilent test =
let config =
Expand All @@ -1031,16 +1037,26 @@ module Impl =
async {
do! config.printer.beforeRun test

ProgressIndicator.text "Expecto Running... "
let progressStarted = ProgressIndicator.start()


let w = Stopwatch.StartNew()
let! results = evalTests config test
let! results = evalTestsWithCancel ct config test progressStarted
w.Stop()
let testSummary = { results = results
duration = w.Elapsed
maxMemory = 0L
memoryLimit = 0L
timedOut = [] }
let testSummary = {
results = results
duration = w.Elapsed
maxMemory = 0L
memoryLimit = 0L
timedOut = []
}
do! config.printer.summary config testSummary

if progressStarted then
ProgressIndicator.stop()
ANSIOutputWriter.Close()

return testSummary.errorCode
}

Expand All @@ -1052,6 +1068,9 @@ module Impl =
async {
do! config.printer.beforeRun test

ProgressIndicator.text "Expecto Running... "
let progressStarted = ProgressIndicator.start()

let tests =
Test.toTestCodeList test
|> List.filter (fun t -> Option.isNone t.shouldSkipEvaluation)
Expand All @@ -1068,11 +1087,13 @@ module Impl =
let next = List.length tests |> rand.Next
List.item next tests

let finishTimestamp =
lazy
let totalTicks =
config.stress.Value.TotalSeconds * float Stopwatch.Frequency
|> int64
|> (+) (Stopwatch.GetTimestamp())

let finishTime =
lazy
totalTicks |> (+) (Stopwatch.GetTimestamp())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember that Stopwatch's ticks differs between operating systems and is not the same as DateTime/BCL ticks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you need to use Stopwatch.Frequency to convert between seconds and Stopwatch ticks. It does this in the lines just above here.


let asyncRun foldRunner (runningTests:ResizeArray<_>,
results,
Expand Down Expand Up @@ -1101,7 +1122,7 @@ module Impl =

Async.Start(async {
let finishMilliseconds =
max (finishTimestamp.Value - Stopwatch.GetTimestamp()) 0L
max (finishTime.Value - Stopwatch.GetTimestamp()) 0L
* 1000L / Stopwatch.Frequency
let timeout =
int finishMilliseconds + int config.stressTimeout.TotalMilliseconds
Expand All @@ -1110,7 +1131,14 @@ module Impl =
}, cancel.Token)

Seq.takeWhile (fun test ->
if Stopwatch.GetTimestamp() < finishTimestamp.Value
let now = Stopwatch.GetTimestamp()

if progressStarted then
100 - int((finishTime.Value - now + totalTicks / 200L) / totalTicks)
|> Percent
|> ProgressIndicator.update

if now < finishTime.Value
&& not ct.IsCancellationRequested then
runningTests.Add test
true
Expand All @@ -1136,7 +1164,7 @@ module Impl =
|> asyncRun Async.foldSequentiallyWithCancel initial
|> Async.bind (fun (runningTests,results,maxMemory) ->
if maxMemory > memoryLimit ||
Stopwatch.GetTimestamp() > finishTimestamp.Value then
Stopwatch.GetTimestamp() > finishTime.Value then
async.Return (runningTests,results,maxMemory)
else
let parallel =
Expand Down Expand Up @@ -1165,6 +1193,10 @@ module Impl =

do! config.printer.summary config testSummary

if progressStarted then
ProgressIndicator.stop()
ANSIOutputWriter.Close()

return testSummary.errorCode
}

Expand Down Expand Up @@ -1325,6 +1357,7 @@ module Impl =
eventX "It was requested that no focused tests exist, but yet there are {count} focused tests found."
>> setField "count" focused.Length)
|> Async.StartImmediate
ANSIOutputWriter.Flush()
false

[<AutoOpen; Extension>]
Expand Down Expand Up @@ -1580,7 +1613,7 @@ module Tests =
| FsCheck_Max_Tests n -> fun o -> {o with fsCheckMaxTests = n }
| FsCheck_Start_Size n -> fun o -> {o with fsCheckStartSize = n }
| FsCheck_End_Size n -> fun o -> {o with fsCheckEndSize = Some n }
| My_Spirit_Is_Weak -> fun o -> { o with mySpiritIsWeak = true }
| My_Spirit_Is_Weak -> id
| Allow_Duplicate_Names -> fun o -> { o with allowDuplicateNames = true }

let parsed =
Expand Down Expand Up @@ -1634,13 +1667,15 @@ module Tests =
| _ ->
None
)

/// Runs tests with the supplied config.
/// Returns 0 if all tests passed, otherwise 1
let runTestsWithCancel (ct:CancellationToken) config (tests:Test) =
Global.initialiseIfDefault
{ Global.defaultConfig with
getLogger = fun name -> LiterateConsoleTarget(name, config.verbosity, consoleSemaphore = Global.semaphore()) :> Logger }
getLogger = fun name ->
LiterateConsoleTarget(name, config.verbosity,
outputWriter = ANSIOutputWriter.TextToOutput,
consoleSemaphore = Global.semaphore()) :> Logger }
config.logName |> Option.iter setLogName
if config.failOnFocusedTests && passesFocusTestCheck config tests |> not then
1
Expand All @@ -1656,6 +1691,7 @@ module Tests =
eventX "Found duplicated test names, these names are: {duplicates}"
>> setField "duplicates" duplicates.Value
) |> Async.RunSynchronously
ANSIOutputWriter.Flush()
1
/// Runs tests with the supplied config.
/// Returns 0 if all tests passed, otherwise 1
Expand Down
1 change: 1 addition & 0 deletions Expecto/Expecto.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Progress.fs" />
<Compile Include="Logging.fs" />
<Compile Include="Statistics.fs" />
<Compile Include="Expecto.fs" />
Expand Down
4 changes: 1 addition & 3 deletions Expecto/Logging.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
/// Original Source:
/// https://github.com/logary/logary/blob/996bdf92713f406b17c6cd7284e4d674f49e3ff6/src/Logary.Facade/Facade.fs
///
/// Changes:
/// Changed namespace to Expecto.Logging and file name to Logging.fs - Anthony Lloyd - 11 Jun 2018
///
namespace Expecto.Logging

open System
open System.Text

/// The log level denotes how 'important' the gauge or event message is.
[<CustomEquality; CustomComparison>]
Expand Down
Loading