public async Task RunsBothBranchesOfSimpleAsynchronousExperimentAndReportsFailure()
        {
            const string experimentName = nameof(RunsBothBranchesOfSimpleAsynchronousExperimentAndReportsFailure);

            var resultPublisher = new InMemoryResultPublisher();
            var science         = new Scientist(resultPublisher);

            var result = await science.ExperimentAsync <int>(experimentName, experiment =>
            {
                experiment.Use(() => Task.FromResult(42));
                experiment.Try(() => Task.FromResult(37));
            });

            Assert.Equal(42, result);
            Assert.False(resultPublisher.Results <int>(experimentName).First().Matched);
            Assert.True(resultPublisher.Results <int>(experimentName).First().Mismatched);
        }
        public async Task RunsBothBranchesOfTheExperimentAndThrowsCorrectInnerExceptionForInstance()
        {
            var mock               = Substitute.For <IControlCandidate <Task <int> > >();
            var controlException   = new InvalidOperationException(null, new Exception());
            var candidateException = new InvalidOperationException(null, new Exception());

            mock.Control().Returns <Task <int> >(x => { throw controlException; });
            mock.Candidate().Returns <Task <int> >(x => { throw controlException; });
            const string experimentName = nameof(RunsBothBranchesOfTheExperimentAndThrowsCorrectInnerException);

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new Scientist(resultPublisher);

            await Assert.ThrowsAsync <InvalidOperationException>(async() =>
            {
                await scientist.ExperimentAsync <int>(experimentName, experiment =>
                {
                    experiment.Use(mock.Control);
                    experiment.Try("candidate", mock.Candidate);
                });
            });
        }
        public async Task RunsBothBranchesOfTheExperimentAsyncAndReportsFailureForInstance()
        {
            var mock = Substitute.For <IControlCandidateTask <int> >();

            mock.Control().Returns(Task.FromResult(42));
            mock.Candidate().Returns(Task.FromResult(43));
            const string experimentName = nameof(RunsBothBranchesOfTheExperimentAsyncAndReportsFailure);

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new Scientist(resultPublisher);

            var result = await scientist.ExperimentAsync <int>(experimentName, experiment =>
            {
                experiment.Use(mock.Control);
                experiment.Try("candidate", mock.Candidate);
            });

            Assert.Equal(42, result);
            await mock.Received().Control();

            await mock.Received().Candidate();

            Assert.False(resultPublisher.Results <int>(experimentName).First().Matched);
        }