Allow testing ordering to be specified as declaration, lexicographical, or random. Allow random seed to be specified

This commit is contained in:
Phil Nash 2014-09-15 18:39:31 +01:00
parent ea33961b43
commit fa0122bf54
7 changed files with 72 additions and 5 deletions

View File

@ -170,6 +170,9 @@ namespace Catch {
try
{
config(); // Force config to be constructed
std::srand( m_configData.rngSeed );
Runner runner( m_config );
// Handle list request

View File

@ -791,7 +791,7 @@ namespace Clara {
if( it == itEnd ) {
if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
unusedTokens.push_back( token );
else if( m_throwOnUnrecognisedTokens )
else if( errors.empty() && m_throwOnUnrecognisedTokens )
errors.push_back( "unrecognised option: " + token.data );
}
}

View File

@ -29,7 +29,28 @@ namespace Catch {
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
else
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
}
inline void setOrder( ConfigData& config, std::string const& order ) {
if( startsWith( "declared", order ) )
config.runOrder = RunTests::InDeclarationOrder;
else if( startsWith( "lexical", order ) )
config.runOrder = RunTests::InLexicographicalOrder;
else if( startsWith( "random", order ) )
config.runOrder = RunTests::InRandomOrder;
else
throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
}
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
if( seed == "time" ) {
config.rngSeed = static_cast<unsigned int>( std::time(0) );
}
else {
std::stringstream ss;
ss << seed;
ss >> config.rngSeed;
if( ss.fail() )
throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
}
}
inline void setVerbosity( ConfigData& config, int level ) {
// !TBD: accept strings?
@ -141,6 +162,14 @@ namespace Catch {
.describe( "list all reporters" )
.bind( &ConfigData::listReporters );
cli["--order"]
.describe( "test case order (defaults to decl)" )
.bind( &setOrder, "decl|lex|rand" );
cli["--rng-seed"]
.describe( "set a specific seed for random numbers" )
.bind( &setRngSeed, "'time'|number" );
return cli;
}

View File

@ -17,6 +17,7 @@
#include <vector>
#include <string>
#include <iostream>
#include <ctime>
#ifndef CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_CONSOLE_WIDTH 80
@ -37,9 +38,11 @@ namespace Catch {
showHelp( false ),
showInvisibles( false ),
abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter )
showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder )
{}
bool listTests;
@ -54,10 +57,12 @@ namespace Catch {
bool showInvisibles;
int abortAfter;
unsigned int rngSeed;
Verbosity::Level verbosity;
WarnAbout::What warnings;
ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
std::string reporterName;
std::string outputFilename;
@ -141,7 +146,8 @@ namespace Catch {
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
virtual unsigned int rngSeed() const { return m_data.rngSeed; }
private:
ConfigData m_data;

View File

@ -32,6 +32,11 @@ namespace Catch {
Always,
Never
}; };
struct RunTests { enum InWhatOrder {
InDeclarationOrder,
InLexicographicalOrder,
InRandomOrder
}; };
class TestSpec;
@ -49,6 +54,8 @@ namespace Catch {
virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0;
virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
};
}

View File

@ -59,7 +59,15 @@ namespace Catch {
return m_nonHiddenFunctions;
}
struct LexSort {
bool operator() (TestCase i,TestCase j) { return (i<j);}
};
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
struct RandomNumberGenerator {
int operator()( int n ) { return std::rand() % n; }
};
for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
itEnd = m_functionsInOrder.end();
it != itEnd;
@ -67,6 +75,17 @@ namespace Catch {
if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) )
matchingTestCases.push_back( *it );
}
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
break;
case RunTests::InRandomOrder:
std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), RandomNumberGenerator() );
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
}
}
private:

View File

@ -271,6 +271,9 @@ namespace Catch {
stream << " host application.\n"
<< "Run with -? for options\n\n";
if( m_config->rngSeed() != 0 )
stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
currentTestRunInfo.used = true;
}
void lazyPrintGroupInfo() {