SlideShare a Scribd company logo
Increase the quality of your code
with property-based testing and FsCheck
Oleksandr Valetskyy
Technical Leader
SoftServe
About me
Introduction
Property-based testing
101
FsCheck testing tool
Properties patterns
Introduction
Agile manifesto emphasizes
- Frequent delivery
- Consistent development
pace
- Accommodating
requirements change
- Working software
- Customer satisfaction
Introduction
Agile manifesto emphasizes
- Frequent delivery
- Consistent development
pace
- Accommodating
requirements change
- Working software
- Customer satisfaction
Software bugs cost the U.S.
economy $59.5 billion
annually. More than a third
of this cost could be
avoided, if better software
testing was performed
(NIST, 2002)
The flipside
Software Fail Watch: 2016 in Review
https://www.tricentis.com/resource-assets/software-fail-
watch-2016/
During 2016, Raygun’s crash and error
reporting software ingested 7.7 billion
errors in total, which averages ~21
million per day.
Some of larger customers sent 50 million
crashes per month.
Software quality
Agile Adoption: Improving Software Quality
https://dzone.com/refcardz/agile-adoption-improving
Software testing verifies SUT (system-under-test)
• meets the requirements that guided its design
and development
• responds correctly to all kinds of inputs
• performs its functions within an acceptable
time,
• is sufficiently usable
• can be installed and run in its intended
environments, and
• achieves the general result its stakeholders
desire.
Automated tests
• By far the most commonly
used approach to ensure
software quality
• Easily cover base flows and
edge cases in requirements
• Can be run unattended and
on schedule, can verify
something manual testing
can’t (e.g. load test)
• Easy to maintain* and
expand
Automated testing drawbacks
• Initial investment - can add up
to 50% of development time
• Writing tests upfront as best
practices suggest is not
possible in most of the cases
• Tests failures do not always
give 100% confidence there are
problems with BL
• Implementing tests may be not
as exciting as other activities^^
Not us, definitely?
Example: shopping with discounts
Covering functionality with unit tests
Plot Twist
Yellow Sticker Discount
┬──┬ ノ( ゜-゜ノ)
Property-based testing to the rescue!
Instead of defining actual VALUES in tests
and compare them we can verify
PROPERTIES of the rules
Arguments can be generated automatically
and be completely random
Yellow Sticker Discount Property-Based Tests
History
QuickCheck is a combinator
library originally written in Haskell,
designed to assist in software
testing by generating test cases for test
suites.
In QuickCheck the programmer writes
assertions about logical properties that
a function should fulfill. Then
QuickCheck attempts to generate a test
case that falsifies these assertions.
Once such a test case is found,
QuickCheck tries to reduce it to a
minimal failing subset by removing or
simplifying input data that are not
needed to make the test fail.
The project was started in 1999.
Currently there exist implementations
of QuickCheck for 30+ modernhttp://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf
Property-based testing 101
Property-based testing (PBT) is a testing technique
that
tries to falsify a given property by generating
random input data and verifying the expected
behavior.
Properties can range from simple algebraic
equations to complex state machine models.
Like in all model-based testing techniques the
properties serve as a source for test-case
generation as well
Value-based vs. property-based testing
Assign inputs for case #1
Do the processing
Assert result
Assign inputs for case #2
Do the processing
Assert result
Assign inputs for case #3
Do the processing
Assert result
Describe the inputs
Describe the result
Profit!
FsCheck
.NET implementation of QuickCheck
written in F#
Works with specifications that are
expressed in F#, C# or VB.
FsCheck provides combinators to define
properties, observe the distribution of test
data, and define test data generators.
Used by:
FSharpx.Extras LinqOptimizer Neutronium
https://fscheck.github.io
FsCheck Generators
Generator – FsCheck.Gen<T> - tries to
create example inputs that tend
to grow larger. It begins by
generating small test cases, and
gradually increases the size as testing
progresses.
There are numerous built-in
generators for typical input types
(ints, floats, strings, lists, etc.) and
also possibility to generate custom
generators.
Built-in Generators
• Gen.Constant – always returns the same value
• Gen.Choose – generates singular integer values between a
minimum and maximum value
• Gen.Elements – generates singular values drawn from a
collection of possible values
• Gen.Map – gives ability to produce generator of one type
from another type
• Gen.ListOfLength – generate lists from individual value
generators
• Gen.Shuffle – a generator that generates a random
permutation of a given finite sequence.
• Gen.Two, Gen.Three, Gen.Four – generating tuples
• Gen.Filter – gives ability to apply custom rules for
generating values
Custom recursive tree generator
FsCheck Shrinkers
When a property fails, FsCheck
automatically displays a minimal
counter example.
This is done with the help of
Shrinker T ->
IEnumerable<T> function that
works hand-in-hand with the
generator such that when a
failure is found, the input that
caused the failure is then
'shrunk' trying to find a smaller
input that also causes a failure.
FsCheck defines default test data generators and
shrinkers for some often used types, for example
unit, bool, byte, int, float, char, string, DateTime,
lists, array 1D and 2D, Set, Map, objects and
functions from and to any of the above.
Furthermore, by using reflection, FsCheck can derive
default implementations of record types,
discriminated unions, tuples, enums and basic classes
in terms of any primitive types that are defined (either
in FsCheck or by you).
FsCheck Shrinkers
3D vector shrinker example
Examples from OSS: Faker
faker-csharp/blob/master/tests/Faker.Models.Tests/ArrayHelperSpecs.cs
[TestFixture(Description = "Validates our extension methods for working with arrays")]
public class ArrayHelperSpecs
{
[Test(Description = "Ensure that our shuffle function works over a range of
intervals")]
public void Shuffled_lists_should_never_match_original()
{
Prop.ForAll<int[]>(original =>
{
var shuffle = original.Shuffle().ToArray();
return (!original.SequenceEqual(shuffle))
.When(original.Length > 1 && original.Distinct().Count() > 1)
.Label($"Expected shuffle({string.Join(",", shuffle)}) to be "
+ $"different than original({string.Join(",", original)})")
.And(original.All(x => shuffle.Contains(x))
.Label($"Expected shuffle({string.Join(",", shuffle)}) to contain"
+ $" same items as original({string.Join(",", original)})"));
}).QuickCheckThrowOnFailure();
}
}
protected JavascriptFactoryBulk_Tests(IBasicWindowLessHTMLEngineProvider testEnvironment,
ITestOutputHelper output) : base(testEnvironment, output)
{
Arb.Register<TestDataGenerator>();
}
public class TestDataGenerator
{
private static Gen<DateTime> DateTimeGenerator => Gen.zip3(Gen.Choose(1800, 2020),
Gen.Choose(0, 365), Gen.zip(Gen.Choose(0, 24), Gen.Choose(0, 3600)))
.Select(t => new DateTime(t.Item1, 1, 1, 0, 0, 0, DateTimeKind.Utc)
.AddDays(t.Item2).AddHours(t.Item3.Item1).AddSeconds(t.Item3.Item2));
private static Gen<T> DefaultGenerator<T>() => Arb.From<T>().Generator;
private static Gen<object> DefaultObjectGenerator<T>() =>
DefaultGenerator<T>().Select(t => (object)t);
private static Gen<object> ObjectGenerator =>
Gen.OneOf(DefaultObjectGenerator<Boolean>(), DefaultObjectGenerator<int>(),
DefaultObjectGenerator<double>(), DefaultGenerator<string>()
.Where(s => !string.IsNullOrEmpty(s))
.Select(t => (object)t), DateTimeGenerator.Select(t => (object)t));
public static Arbitrary<DateTime> ArbitraryDateTime() => Arb.From(DateTimeGenerator);
public static Arbitrary<object> ArbitraryObject() => Arb.From(ObjectGenerator);
}
Examples from OSS: Neutronium
NeutroniumCore/Neutronium/Tests/UniversalTests/Tests.Universal.WebBrowserEngineTests/JavascriptFa
[Theory]
[InlineData(false)]
[InlineData(true)]
[InlineData(10)]
[InlineData(0.5D)]
[InlineData(-1)]
[InlineData(99999.95)]
[InlineData(2.333333333)]
[InlineData(-0.66666666666666663)]
[InlineData(1.3333333333333333)]
[InlineData(double.NegativeInfinity)]
[InlineData("tititi")]
[InlineData("")]
[InlineData("n")]
[InlineData("rn")]
[InlineData("r")]
[InlineData("'")]
public void CreateBasics_BasicTypes_Returns_Correct_Value(object value)
{
TestConversion(value);
}
[Property]
public Property CreateBasics_Int_Create_Correct_Objects()
{
return CreateBasics_Returns_Correct_Value<int>();
}
[Property(Skip = "Decimal precision is not supported")]
public Property CreateBasics_Decimal_Create_Correct_Objects()
{
return CreateBasics_Returns_Correct_Value<decimal>();
}
[Property]
public Property CreateBasics_Double_Create_Correct_Objects()
{
return CreateBasics_Returns_Correct_Value<double>();
}
[Property]
public Property CreateBasics_DateTime_Create_Correct_Objects()
{
return CreateBasics_Returns_Correct_Value<DateTime>();
}
[Property]
public Property CreateBasics_String_Create_Correct_Objects()
{
Func<string, bool> when = Always<string>;
if (!SupportStringEmpty) when = StringIsNotEmpty;
return CreateBasics_Returns_Correct_Value(when);
}
Neutronium (cont’d)
Examples from OSS: LinqOptimizer
LinqOptimizer/tests/LinqOptimizer.Tests.CSharp/QueryTests.cs
[TestFixture]
public class QueryTests
{
[Test]
public void Select()
{
Func<IEnumerable<object>, bool> f = xs =>
{
var x = xs.AsQueryExpr().Select(n => n.ToString()).Run();
var y = xs.Select(n => n.ToString());
return Enumerable.SequenceEqual(x, y); };
Spec.ForAny<TestInput<object>>(xs =>
TestInput<object>.RunTestFunc<object>(f, xs))
.QuickCheckThrowOnFailure(); }
[Test]
public void Pipelined()
{
Spec.ForAny<int[]>(xs =>
{
var x = xs.AsQueryExpr().Where(n => n % 2 == 0)
.Select(n => n * 2).Select(n => n.ToString()).Select(n => n + "!").Run();
var y = xs .Where(n => n % 2 == 0)
.Select(n => n * 2) .Select(n => n.ToString()).Select(n => n + "!");
return Enumerable.SequenceEqual(x, y);
}).QuickCheckThrowOnFailure();
}
}
.ToArbitrary() – constructs an arbitrary instance
from generator
.Classify() – classifies test cases. Test cases
satisfying the condition are assigned the
classification given.
.Label () – adds the given label to the property.
The labels of a failing sub-property are displayed
when it fails.
.Sample (int size) – Generates n values of the
given size.
.VerboseCheckThrowOnFailure() – throws an
exception with the error message if the test fails or
is exhausted
Other points of interest
Caveat
[Property(QuietOnSuccess = false, MaxTest = 1000)]
public bool Test_To_Be_Run_Thousand_Times()
{
return true;
}
Configuring FsCheck
public class CapturingOutput
{
private readonly ITestOutputHelper _testOutputHelper;
public CapturingOutput(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
[Fact]
public void CapturingOutput_Example()
{
Prop.ForAll(Arb.Default.Bool(), i => i)
.VerboseCheckThrowOnFailure(_testOutputHelper);
}
}
Capturing output
public class ReplayExample
{
[Fact]
public void Replay_Example()
{
Prop.ForAll(Arb.Default.Bool(), i => i)
.Check(new Configuration
{
Replay = Random.StdGen.NewStdGen(487723102, 296400248)
});
}
}
Replaying failed test
Quick summary
Not a silver bullet!
Property-based testing is yet another approach to
software testing
It may look as pure magic at first, but can help in
cases when conventional tests are hard to
implement or not efficient
Does not substitute value-based testing, but
complements it nicely
Gives another perspective and mindset during
coding and verification
Philosophical detour
There are two ways of constructing a software design:
One way is to make it so simple that there are obviously no
deficiencies, and the other way is to make it so complicated that
there are no obvious deficiencies.
The first method is far more difficult. It demands the same skill,
devotion, insight, and even inspiration as the discovery of the
simple physical laws which underlie the complex phenomena of
nature.
Charles Antony Richard Hoare (Tony Hoare)
1980 Turing Award Lecture
Properties patterns
“Different paths, same destination”
Combining operations in different
orders, but getting the same result
Examples:
Addition commutativity
Sorting lists
List reversal
Properties patterns
“There and back again”
Combining some operation with its
inverse should produce the source
input
Examples:
Any inverse operation
Addition/substraction
Write/read
Serialize/deserialize
Encipher/decipher
Set/get
Insert/contains
Create/exists
Properties patterns
“Some things never change”
Checking some invariant that is
preserved during transformation
Examples:
Size of collection
Contents of a collection
Measures proportion during scaling
Properties patterns
“The more things change, the more
they stay the same”
Idempotence property – doing the
same operation twice should be the
same as doing it once
Examples:
Database filtering
Database updates
Message processing
SOA?
Properties patterns
“Solve a smaller problem first”
Structural induction – if something
can be broken into smaller parts
and we prove some property is
true for all of them, we can prove
the property is true for the whole
structure
Examples:
Operations with recursive
structures such as lists and trees
Properties patterns
“Hard to prove, easy to verify”
Verifying results of some algorithm
is way easier than finding the
solution
Examples:
Shortest path in maze vs. valid path
Sort list/verify it is sorted
Prime number factorization
String tokenizer
Properties patterns
“The test oracle” aka “Two heads are
better than one”
Using alternate (simplified*) version
of an algorithm or process (a “test
oracle”) to check results
Examples:
Optimized high-performance
algorithm vs. brute force version
Parallel/concurrent algorithm vs.
linear/single-thread version
Data generators
An introduction to property-based testing Or, why you should be using FsCheck and QuickCheck
https://fsharpforfunandprofit.com/posts/property-based-testing/
The lazy programmer's guide to writing 1000's of tests: An introduction to property based testing
https://skillsmatter.com/skillscasts/6432-the-lazy-programmers-guide-to-writing-1000s-of-
tests-an-introduction-to-property-based-testing
FsCheck
https://fscheck.github.io/FsCheck/index.html
QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs by Koen Claessen and John
Hughes
http://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf
Software Fail Watch: 2016 in Review
https://www.tricentis.com/resource-assets/software-fail-watch-2016/
Property-based Testing with FsCheck by Deriving Properties from Business Rule Models. IEEE, 2016.
http://truconf.ist.tugraz.at/index.php/2016/03/04/publication-at-a-most-2016/
Agile Adoption: Improving Software Quality. Reducing Bugs and Improving Design
https://dzone.com/refcardz/agile-adoption-improving
John Hughes: Race Conditions, Distribution, Interactions — Testing the Hard Stuff and Staying Sane
https://vimeo.com/68383317
Discounts and allowances wiki article
https://en.wikipedia.org/wiki/Discounts_and_allowances#Dealing_with_quantity
Neutronium Github
https://github.com/NeutroniumCore/Neutronium
Real World Haskell by Bryan O'Sullivan, Don Stewart, and John Goerzen
http://book.realworldhaskell.org/read/testing-and-quality-assurance.html
Exploring Test-Driven Development with QuickCheck
http://www.natpryce.com/articles/000795.html
Unit Test Boilerplate Generator
References:
Thank you!

More Related Content

What's hot

How to Profit from Static Analysis
How to Profit from Static AnalysisHow to Profit from Static Analysis
How to Profit from Static Analysis
Elena Laskavaia
 
Thinking in Properties
Thinking in PropertiesThinking in Properties
Thinking in Properties
Susan Potter
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
Shai Yallin
 
Py.test
Py.testPy.test
Py.test
soasme
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
LB Denker
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheckBeScala
 
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalksSelenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
Lohika_Odessa_TechTalks
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
Suraj Deshmukh
 
Automated Testing in Django
Automated Testing in DjangoAutomated Testing in Django
Automated Testing in Django
Loek van Gent
 
Functions for nothing, and your tests for free
Functions for nothing, and your tests for freeFunctions for nothing, and your tests for free
Functions for nothing, and your tests for free
George Pollard
 
Effective Readable unit testing with junit5
Effective Readable unit testing with junit5Effective Readable unit testing with junit5
Effective Readable unit testing with junit5
Sajith Vijesekara
 
Pytest - testing tips and useful plugins
Pytest - testing tips and useful pluginsPytest - testing tips and useful plugins
Pytest - testing tips and useful plugins
Andreu Vallbona Plazas
 
Model-Driven Testing For Agile Teams
Model-Driven Testing For Agile TeamsModel-Driven Testing For Agile Teams
Model-Driven Testing For Agile Teams
KerryKimbrough
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
John Ferguson Smart Limited
 
Developer testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to IntegrateDeveloper testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to Integrate
LB Denker
 
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
Andrzej Jóźwiak
 
Ember Data and Custom APIs
Ember Data and Custom APIsEmber Data and Custom APIs
Ember Data and Custom APIs
David Tang
 
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTEclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Elena Laskavaia
 
Qtp - Introduction to synchronization
Qtp -  Introduction to synchronizationQtp -  Introduction to synchronization
Qtp - Introduction to synchronization
Vibrant Technologies & Computers
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
Mark Niebergall
 

What's hot (20)

How to Profit from Static Analysis
How to Profit from Static AnalysisHow to Profit from Static Analysis
How to Profit from Static Analysis
 
Thinking in Properties
Thinking in PropertiesThinking in Properties
Thinking in Properties
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
 
Py.test
Py.testPy.test
Py.test
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheck
 
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalksSelenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
Selenium with py test by Alexandr Vasyliev for Lohika Odessa Python TechTalks
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
 
Automated Testing in Django
Automated Testing in DjangoAutomated Testing in Django
Automated Testing in Django
 
Functions for nothing, and your tests for free
Functions for nothing, and your tests for freeFunctions for nothing, and your tests for free
Functions for nothing, and your tests for free
 
Effective Readable unit testing with junit5
Effective Readable unit testing with junit5Effective Readable unit testing with junit5
Effective Readable unit testing with junit5
 
Pytest - testing tips and useful plugins
Pytest - testing tips and useful pluginsPytest - testing tips and useful plugins
Pytest - testing tips and useful plugins
 
Model-Driven Testing For Agile Teams
Model-Driven Testing For Agile TeamsModel-Driven Testing For Agile Teams
Model-Driven Testing For Agile Teams
 
JUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit TestsJUnit Kung Fu: Getting More Out of Your Unit Tests
JUnit Kung Fu: Getting More Out of Your Unit Tests
 
Developer testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to IntegrateDeveloper testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to Integrate
 
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
Property based tests and where to find them - Andrzej Jóźwiak - TomTom Webina...
 
Ember Data and Custom APIs
Ember Data and Custom APIsEmber Data and Custom APIs
Ember Data and Custom APIs
 
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTEclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
 
Qtp - Introduction to synchronization
Qtp -  Introduction to synchronizationQtp -  Introduction to synchronization
Qtp - Introduction to synchronization
 
Unit Testing from Setup to Deployment
Unit Testing from Setup to DeploymentUnit Testing from Setup to Deployment
Unit Testing from Setup to Deployment
 

Similar to Oleksandr Valetskyy - Increase the quality of your code with property-based testing and FsCheck

TDD Training
TDD TrainingTDD Training
TDD Training
Manuela Grindei
 
Static Analysis
Static AnalysisStatic Analysis
Static Analysis
alice yang
 
Software testing
Software testingSoftware testing
Software testing
Enamul Haque
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
davejohnson
 
2 fitnesse
2 fitnesse2 fitnesse
2 fitnesse
Mradul Jain
 
Beginners overview of automated testing with Rspec
Beginners overview of automated testing with RspecBeginners overview of automated testing with Rspec
Beginners overview of automated testing with Rspec
jeffrey1ross
 
Getting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe TestingGetting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe Testing
Mark Rickerby
 
Create an architecture for web test automation
Create an architecture for web test automationCreate an architecture for web test automation
Create an architecture for web test automation
Elias Nogueira
 
Good Practices On Test Automation
Good Practices On Test AutomationGood Practices On Test Automation
Good Practices On Test Automation
Gustavo Labbate Godoy
 
Software testing: an introduction - 2017
Software testing: an introduction - 2017Software testing: an introduction - 2017
Software testing: an introduction - 2017
XavierDevroey
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your Code
Nate Abele
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0
Nate Abele
 
Cm5 secure code_training_1day_system configuration
Cm5 secure code_training_1day_system configurationCm5 secure code_training_1day_system configuration
Cm5 secure code_training_1day_system configuration
dcervigni
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
pleeps
 
Modern Python Testing
Modern Python TestingModern Python Testing
Modern Python Testing
Alexander Loechel
 
justin presentation upload PPT june 19
justin presentation upload PPT june 19justin presentation upload PPT june 19
justin presentation upload PPT june 19techweb08
 
justin for ppt1 by browse button
justin for ppt1 by browse buttonjustin for ppt1 by browse button
justin for ppt1 by browse buttontechweb08
 

Similar to Oleksandr Valetskyy - Increase the quality of your code with property-based testing and FsCheck (20)

TDD Training
TDD TrainingTDD Training
TDD Training
 
Static Analysis
Static AnalysisStatic Analysis
Static Analysis
 
Gallio Crafting A Toolchain
Gallio Crafting A ToolchainGallio Crafting A Toolchain
Gallio Crafting A Toolchain
 
Software testing
Software testingSoftware testing
Software testing
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
 
2 fitnesse
2 fitnesse2 fitnesse
2 fitnesse
 
Beginners overview of automated testing with Rspec
Beginners overview of automated testing with RspecBeginners overview of automated testing with Rspec
Beginners overview of automated testing with Rspec
 
Getting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe TestingGetting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe Testing
 
Create an architecture for web test automation
Create an architecture for web test automationCreate an architecture for web test automation
Create an architecture for web test automation
 
Good Practices On Test Automation
Good Practices On Test AutomationGood Practices On Test Automation
Good Practices On Test Automation
 
Software testing: an introduction - 2017
Software testing: an introduction - 2017Software testing: an introduction - 2017
Software testing: an introduction - 2017
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your Code
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0
 
Cm5 secure code_training_1day_system configuration
Cm5 secure code_training_1day_system configurationCm5 secure code_training_1day_system configuration
Cm5 secure code_training_1day_system configuration
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Modern Python Testing
Modern Python TestingModern Python Testing
Modern Python Testing
 
Paper CS
Paper CSPaper CS
Paper CS
 
alkatest7
alkatest7alkatest7
alkatest7
 
justin presentation upload PPT june 19
justin presentation upload PPT june 19justin presentation upload PPT june 19
justin presentation upload PPT june 19
 
justin for ppt1 by browse button
justin for ppt1 by browse buttonjustin for ppt1 by browse button
justin for ppt1 by browse button
 

Recently uploaded

OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Jay Das
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
Juraj Vysvader
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 

Recently uploaded (20)

OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdfEnhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
Enhancing Project Management Efficiency_ Leveraging AI Tools like ChatGPT.pdf
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
In 2015, I used to write extensions for Joomla, WordPress, phpBB3, etc and I ...
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 

Oleksandr Valetskyy - Increase the quality of your code with property-based testing and FsCheck

  • 1. Increase the quality of your code with property-based testing and FsCheck Oleksandr Valetskyy Technical Leader SoftServe
  • 4. Introduction Agile manifesto emphasizes - Frequent delivery - Consistent development pace - Accommodating requirements change - Working software - Customer satisfaction
  • 5. Introduction Agile manifesto emphasizes - Frequent delivery - Consistent development pace - Accommodating requirements change - Working software - Customer satisfaction
  • 6. Software bugs cost the U.S. economy $59.5 billion annually. More than a third of this cost could be avoided, if better software testing was performed (NIST, 2002) The flipside
  • 7. Software Fail Watch: 2016 in Review https://www.tricentis.com/resource-assets/software-fail- watch-2016/
  • 8. During 2016, Raygun’s crash and error reporting software ingested 7.7 billion errors in total, which averages ~21 million per day. Some of larger customers sent 50 million crashes per month.
  • 9. Software quality Agile Adoption: Improving Software Quality https://dzone.com/refcardz/agile-adoption-improving
  • 10. Software testing verifies SUT (system-under-test) • meets the requirements that guided its design and development • responds correctly to all kinds of inputs • performs its functions within an acceptable time, • is sufficiently usable • can be installed and run in its intended environments, and • achieves the general result its stakeholders desire.
  • 11. Automated tests • By far the most commonly used approach to ensure software quality • Easily cover base flows and edge cases in requirements • Can be run unattended and on schedule, can verify something manual testing can’t (e.g. load test) • Easy to maintain* and expand
  • 12. Automated testing drawbacks • Initial investment - can add up to 50% of development time • Writing tests upfront as best practices suggest is not possible in most of the cases • Tests failures do not always give 100% confidence there are problems with BL • Implementing tests may be not as exciting as other activities^^
  • 15.
  • 16.
  • 18.
  • 21. ┬──┬ ノ( ゜-゜ノ) Property-based testing to the rescue! Instead of defining actual VALUES in tests and compare them we can verify PROPERTIES of the rules Arguments can be generated automatically and be completely random
  • 22. Yellow Sticker Discount Property-Based Tests
  • 23. History QuickCheck is a combinator library originally written in Haskell, designed to assist in software testing by generating test cases for test suites. In QuickCheck the programmer writes assertions about logical properties that a function should fulfill. Then QuickCheck attempts to generate a test case that falsifies these assertions. Once such a test case is found, QuickCheck tries to reduce it to a minimal failing subset by removing or simplifying input data that are not needed to make the test fail. The project was started in 1999. Currently there exist implementations of QuickCheck for 30+ modernhttp://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf
  • 24. Property-based testing 101 Property-based testing (PBT) is a testing technique that tries to falsify a given property by generating random input data and verifying the expected behavior. Properties can range from simple algebraic equations to complex state machine models. Like in all model-based testing techniques the properties serve as a source for test-case generation as well
  • 25. Value-based vs. property-based testing Assign inputs for case #1 Do the processing Assert result Assign inputs for case #2 Do the processing Assert result Assign inputs for case #3 Do the processing Assert result Describe the inputs Describe the result Profit!
  • 26. FsCheck .NET implementation of QuickCheck written in F# Works with specifications that are expressed in F#, C# or VB. FsCheck provides combinators to define properties, observe the distribution of test data, and define test data generators. Used by: FSharpx.Extras LinqOptimizer Neutronium https://fscheck.github.io
  • 27. FsCheck Generators Generator – FsCheck.Gen<T> - tries to create example inputs that tend to grow larger. It begins by generating small test cases, and gradually increases the size as testing progresses. There are numerous built-in generators for typical input types (ints, floats, strings, lists, etc.) and also possibility to generate custom generators.
  • 28. Built-in Generators • Gen.Constant – always returns the same value • Gen.Choose – generates singular integer values between a minimum and maximum value • Gen.Elements – generates singular values drawn from a collection of possible values • Gen.Map – gives ability to produce generator of one type from another type • Gen.ListOfLength – generate lists from individual value generators • Gen.Shuffle – a generator that generates a random permutation of a given finite sequence. • Gen.Two, Gen.Three, Gen.Four – generating tuples • Gen.Filter – gives ability to apply custom rules for generating values
  • 30. FsCheck Shrinkers When a property fails, FsCheck automatically displays a minimal counter example. This is done with the help of Shrinker T -> IEnumerable<T> function that works hand-in-hand with the generator such that when a failure is found, the input that caused the failure is then 'shrunk' trying to find a smaller input that also causes a failure.
  • 31. FsCheck defines default test data generators and shrinkers for some often used types, for example unit, bool, byte, int, float, char, string, DateTime, lists, array 1D and 2D, Set, Map, objects and functions from and to any of the above. Furthermore, by using reflection, FsCheck can derive default implementations of record types, discriminated unions, tuples, enums and basic classes in terms of any primitive types that are defined (either in FsCheck or by you). FsCheck Shrinkers
  • 33. Examples from OSS: Faker faker-csharp/blob/master/tests/Faker.Models.Tests/ArrayHelperSpecs.cs [TestFixture(Description = "Validates our extension methods for working with arrays")] public class ArrayHelperSpecs { [Test(Description = "Ensure that our shuffle function works over a range of intervals")] public void Shuffled_lists_should_never_match_original() { Prop.ForAll<int[]>(original => { var shuffle = original.Shuffle().ToArray(); return (!original.SequenceEqual(shuffle)) .When(original.Length > 1 && original.Distinct().Count() > 1) .Label($"Expected shuffle({string.Join(",", shuffle)}) to be " + $"different than original({string.Join(",", original)})") .And(original.All(x => shuffle.Contains(x)) .Label($"Expected shuffle({string.Join(",", shuffle)}) to contain" + $" same items as original({string.Join(",", original)})")); }).QuickCheckThrowOnFailure(); } }
  • 34. protected JavascriptFactoryBulk_Tests(IBasicWindowLessHTMLEngineProvider testEnvironment, ITestOutputHelper output) : base(testEnvironment, output) { Arb.Register<TestDataGenerator>(); } public class TestDataGenerator { private static Gen<DateTime> DateTimeGenerator => Gen.zip3(Gen.Choose(1800, 2020), Gen.Choose(0, 365), Gen.zip(Gen.Choose(0, 24), Gen.Choose(0, 3600))) .Select(t => new DateTime(t.Item1, 1, 1, 0, 0, 0, DateTimeKind.Utc) .AddDays(t.Item2).AddHours(t.Item3.Item1).AddSeconds(t.Item3.Item2)); private static Gen<T> DefaultGenerator<T>() => Arb.From<T>().Generator; private static Gen<object> DefaultObjectGenerator<T>() => DefaultGenerator<T>().Select(t => (object)t); private static Gen<object> ObjectGenerator => Gen.OneOf(DefaultObjectGenerator<Boolean>(), DefaultObjectGenerator<int>(), DefaultObjectGenerator<double>(), DefaultGenerator<string>() .Where(s => !string.IsNullOrEmpty(s)) .Select(t => (object)t), DateTimeGenerator.Select(t => (object)t)); public static Arbitrary<DateTime> ArbitraryDateTime() => Arb.From(DateTimeGenerator); public static Arbitrary<object> ArbitraryObject() => Arb.From(ObjectGenerator); } Examples from OSS: Neutronium NeutroniumCore/Neutronium/Tests/UniversalTests/Tests.Universal.WebBrowserEngineTests/JavascriptFa
  • 35. [Theory] [InlineData(false)] [InlineData(true)] [InlineData(10)] [InlineData(0.5D)] [InlineData(-1)] [InlineData(99999.95)] [InlineData(2.333333333)] [InlineData(-0.66666666666666663)] [InlineData(1.3333333333333333)] [InlineData(double.NegativeInfinity)] [InlineData("tititi")] [InlineData("")] [InlineData("n")] [InlineData("rn")] [InlineData("r")] [InlineData("'")] public void CreateBasics_BasicTypes_Returns_Correct_Value(object value) { TestConversion(value); } [Property] public Property CreateBasics_Int_Create_Correct_Objects() { return CreateBasics_Returns_Correct_Value<int>(); } [Property(Skip = "Decimal precision is not supported")] public Property CreateBasics_Decimal_Create_Correct_Objects() { return CreateBasics_Returns_Correct_Value<decimal>(); } [Property] public Property CreateBasics_Double_Create_Correct_Objects() { return CreateBasics_Returns_Correct_Value<double>(); } [Property] public Property CreateBasics_DateTime_Create_Correct_Objects() { return CreateBasics_Returns_Correct_Value<DateTime>(); } [Property] public Property CreateBasics_String_Create_Correct_Objects() { Func<string, bool> when = Always<string>; if (!SupportStringEmpty) when = StringIsNotEmpty; return CreateBasics_Returns_Correct_Value(when); } Neutronium (cont’d)
  • 36. Examples from OSS: LinqOptimizer LinqOptimizer/tests/LinqOptimizer.Tests.CSharp/QueryTests.cs [TestFixture] public class QueryTests { [Test] public void Select() { Func<IEnumerable<object>, bool> f = xs => { var x = xs.AsQueryExpr().Select(n => n.ToString()).Run(); var y = xs.Select(n => n.ToString()); return Enumerable.SequenceEqual(x, y); }; Spec.ForAny<TestInput<object>>(xs => TestInput<object>.RunTestFunc<object>(f, xs)) .QuickCheckThrowOnFailure(); } [Test] public void Pipelined() { Spec.ForAny<int[]>(xs => { var x = xs.AsQueryExpr().Where(n => n % 2 == 0) .Select(n => n * 2).Select(n => n.ToString()).Select(n => n + "!").Run(); var y = xs .Where(n => n % 2 == 0) .Select(n => n * 2) .Select(n => n.ToString()).Select(n => n + "!"); return Enumerable.SequenceEqual(x, y); }).QuickCheckThrowOnFailure(); } }
  • 37. .ToArbitrary() – constructs an arbitrary instance from generator .Classify() – classifies test cases. Test cases satisfying the condition are assigned the classification given. .Label () – adds the given label to the property. The labels of a failing sub-property are displayed when it fails. .Sample (int size) – Generates n values of the given size. .VerboseCheckThrowOnFailure() – throws an exception with the error message if the test fails or is exhausted Other points of interest
  • 39. [Property(QuietOnSuccess = false, MaxTest = 1000)] public bool Test_To_Be_Run_Thousand_Times() { return true; } Configuring FsCheck
  • 40. public class CapturingOutput { private readonly ITestOutputHelper _testOutputHelper; public CapturingOutput(ITestOutputHelper testOutputHelper) { _testOutputHelper = testOutputHelper; } [Fact] public void CapturingOutput_Example() { Prop.ForAll(Arb.Default.Bool(), i => i) .VerboseCheckThrowOnFailure(_testOutputHelper); } } Capturing output
  • 41. public class ReplayExample { [Fact] public void Replay_Example() { Prop.ForAll(Arb.Default.Bool(), i => i) .Check(new Configuration { Replay = Random.StdGen.NewStdGen(487723102, 296400248) }); } } Replaying failed test
  • 42. Quick summary Not a silver bullet! Property-based testing is yet another approach to software testing It may look as pure magic at first, but can help in cases when conventional tests are hard to implement or not efficient Does not substitute value-based testing, but complements it nicely Gives another perspective and mindset during coding and verification
  • 43. Philosophical detour There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult. It demands the same skill, devotion, insight, and even inspiration as the discovery of the simple physical laws which underlie the complex phenomena of nature. Charles Antony Richard Hoare (Tony Hoare) 1980 Turing Award Lecture
  • 44. Properties patterns “Different paths, same destination” Combining operations in different orders, but getting the same result Examples: Addition commutativity Sorting lists List reversal
  • 45. Properties patterns “There and back again” Combining some operation with its inverse should produce the source input Examples: Any inverse operation Addition/substraction Write/read Serialize/deserialize Encipher/decipher Set/get Insert/contains Create/exists
  • 46. Properties patterns “Some things never change” Checking some invariant that is preserved during transformation Examples: Size of collection Contents of a collection Measures proportion during scaling
  • 47. Properties patterns “The more things change, the more they stay the same” Idempotence property – doing the same operation twice should be the same as doing it once Examples: Database filtering Database updates Message processing SOA?
  • 48. Properties patterns “Solve a smaller problem first” Structural induction – if something can be broken into smaller parts and we prove some property is true for all of them, we can prove the property is true for the whole structure Examples: Operations with recursive structures such as lists and trees
  • 49. Properties patterns “Hard to prove, easy to verify” Verifying results of some algorithm is way easier than finding the solution Examples: Shortest path in maze vs. valid path Sort list/verify it is sorted Prime number factorization String tokenizer
  • 50. Properties patterns “The test oracle” aka “Two heads are better than one” Using alternate (simplified*) version of an algorithm or process (a “test oracle”) to check results Examples: Optimized high-performance algorithm vs. brute force version Parallel/concurrent algorithm vs. linear/single-thread version Data generators
  • 51.
  • 52. An introduction to property-based testing Or, why you should be using FsCheck and QuickCheck https://fsharpforfunandprofit.com/posts/property-based-testing/ The lazy programmer's guide to writing 1000's of tests: An introduction to property based testing https://skillsmatter.com/skillscasts/6432-the-lazy-programmers-guide-to-writing-1000s-of- tests-an-introduction-to-property-based-testing FsCheck https://fscheck.github.io/FsCheck/index.html QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs by Koen Claessen and John Hughes http://www.eecs.northwestern.edu/~robby/courses/395-495-2009-fall/quick.pdf Software Fail Watch: 2016 in Review https://www.tricentis.com/resource-assets/software-fail-watch-2016/ Property-based Testing with FsCheck by Deriving Properties from Business Rule Models. IEEE, 2016. http://truconf.ist.tugraz.at/index.php/2016/03/04/publication-at-a-most-2016/ Agile Adoption: Improving Software Quality. Reducing Bugs and Improving Design https://dzone.com/refcardz/agile-adoption-improving John Hughes: Race Conditions, Distribution, Interactions — Testing the Hard Stuff and Staying Sane https://vimeo.com/68383317 Discounts and allowances wiki article https://en.wikipedia.org/wiki/Discounts_and_allowances#Dealing_with_quantity Neutronium Github https://github.com/NeutroniumCore/Neutronium Real World Haskell by Bryan O'Sullivan, Don Stewart, and John Goerzen http://book.realworldhaskell.org/read/testing-and-quality-assurance.html Exploring Test-Driven Development with QuickCheck http://www.natpryce.com/articles/000795.html Unit Test Boilerplate Generator References:
  • 53.