Skip to content

Add solo_test, solo_group API #446

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

Closed
wants to merge 1 commit into from
Closed
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
62 changes: 54 additions & 8 deletions lib/src/backend/declarer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class Declarer {
/// Whether [build] has been called for this declarer.
bool _built = false;

/// Whether a solo test or solo group has been encountered.
bool _soloSeen = false;

/// The current zone-scoped declarer.
static Declarer get current => Zone.current[#test.declarer];

Expand All @@ -88,12 +91,25 @@ class Declarer {
declare(body()) => runZoned(body, zoneValues: {#test.declarer: this});

/// Defines a test case with the given name and body.
void test(String name, body(), {String testOn, Timeout timeout, skip,
Map<String, dynamic> onPlatform, tags}) {
void test(String name, body(),
{String testOn,
Timeout timeout,
skip,
solo,
Map<String, dynamic> onPlatform,
tags}) {
_checkNotBuilt("test");

if (solo) {
_soloSeen = true;
}

var metadata = _metadata.merge(new Metadata.parse(
testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform,
testOn: testOn,
timeout: timeout,
skip: skip,
solo: solo,
onPlatform: onPlatform,
tags: tags));

_entries.add(new LocalTest(_prefix(name), metadata, () async {
Expand All @@ -110,18 +126,34 @@ class Declarer {
}

/// Creates a group of tests.
void group(String name, void body(), {String testOn, Timeout timeout, skip,
Map<String, dynamic> onPlatform, tags}) {
void group(String name, void body(),
{String testOn,
Timeout timeout,
skip,
solo,
Map<String, dynamic> onPlatform,
tags}) {
_checkNotBuilt("group");

if (solo) {
_soloSeen = true;
}

var metadata = _metadata.merge(new Metadata.parse(
testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform,
testOn: testOn,
timeout: timeout,
skip: skip,
solo: solo,
onPlatform: onPlatform,
tags: tags));
var trace = new Trace.current(2);

var declarer = new Declarer._(this, _prefix(name), metadata, trace);
declarer.declare(body);
_entries.add(declarer.build());
if (declarer._soloSeen) {
_soloSeen = true;
}
_entries.add(declarer.build(soloSeenInParent: _soloSeen));
}

/// Returns [name] prefixed with this declarer's group name.
Expand Down Expand Up @@ -154,9 +186,13 @@ class Declarer {
}

/// Finalizes and returns the group being declared.
Group build() {
Group build({bool soloSeenInParent: false}) {
_checkNotBuilt("build");

if (_soloSeen || soloSeenInParent) {
_skipNonSoloEntries(_entries);
}

_built = true;
return new Group(_name, _entries.toList(),
metadata: _metadata,
Expand All @@ -165,6 +201,16 @@ class Declarer {
tearDownAll: _tearDownAll);
}

void _skipNonSoloEntries(List<GroupEntry> entries) {
entries.where((entry) => !entry.metadata.solo).forEach((entry) {
if (entry is Group) {
_skipNonSoloEntries(entry.entries);
} else {
entry.metadata.skip = true;
}
});
}

/// Throws a [StateError] if [build] has been called.
///
/// [name] should be the name of the method being called.
Expand Down
25 changes: 17 additions & 8 deletions lib/src/backend/metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ class Metadata {
final Timeout timeout;

/// Whether the test or suite should be skipped.
final bool skip;
bool skip;

/// Whether this is a solo test or suite.
bool solo;

/// Whether to use verbose stack traces.
final bool verboseTrace;
Expand Down Expand Up @@ -123,14 +126,15 @@ class Metadata {
/// included inline in the returned value. The values directly passed to the
/// constructor take precedence over tag-specific metadata.
factory Metadata({PlatformSelector testOn, Timeout timeout, bool skip: false,
bool verboseTrace: false, String skipReason, Iterable<String> tags,
Map<PlatformSelector, Metadata> onPlatform,
bool solo: false, bool verboseTrace: false, String skipReason,
Iterable<String> tags, Map<PlatformSelector, Metadata> onPlatform,
Map<BooleanSelector, Metadata> forTag}) {
// Returns metadata without forTag resolved at all.
_unresolved() => new Metadata._(
testOn: testOn,
timeout: timeout,
skip: skip,
solo: solo,
verboseTrace: verboseTrace,
skipReason: skipReason,
tags: tags,
Expand Down Expand Up @@ -160,8 +164,8 @@ class Metadata {
///
/// Unlike [new Metadata], this assumes [forTag] is already resolved.
Metadata._({PlatformSelector testOn, Timeout timeout, bool skip: false,
this.verboseTrace: false, this.skipReason, Iterable<String> tags,
Map<PlatformSelector, Metadata> onPlatform,
this.solo: false, this.verboseTrace: false, this.skipReason,
Iterable<String> tags, Map<PlatformSelector, Metadata> onPlatform,
Map<BooleanSelector, Metadata> forTag})
: testOn = testOn == null ? PlatformSelector.all : testOn,
timeout = timeout == null ? const Timeout.factor(1) : timeout,
Expand All @@ -181,7 +185,7 @@ class Metadata {
/// where applicable.
///
/// Throws a [FormatException] if any field is invalid.
Metadata.parse({String testOn, Timeout timeout, skip,
Metadata.parse({String testOn, Timeout timeout, skip, solo,
this.verboseTrace: false, Map<String, dynamic> onPlatform,
tags})
: testOn = testOn == null
Expand All @@ -190,6 +194,7 @@ class Metadata {
timeout = timeout == null ? const Timeout.factor(1) : timeout,
skip = skip != null && skip != false,
skipReason = skip is String ? skip : null,
solo = solo != null && solo != false,
onPlatform = _parseOnPlatform(onPlatform),
tags = _parseTags(tags),
forTag = const {} {
Expand All @@ -209,6 +214,7 @@ class Metadata {
timeout = _deserializeTimeout(serialized['timeout']),
skip = serialized['skip'],
skipReason = serialized['skipReason'],
solo = serialized['solo'],
verboseTrace = serialized['verboseTrace'],
tags = new Set.from(serialized['tags']),
onPlatform = new Map.fromIterable(serialized['onPlatform'],
Expand Down Expand Up @@ -254,6 +260,7 @@ class Metadata {
timeout: timeout.merge(other.timeout),
skip: skip || other.skip,
skipReason: other.skipReason == null ? skipReason : other.skipReason,
solo: solo || other.solo,
verboseTrace: verboseTrace || other.verboseTrace,
tags: tags.union(other.tags),
onPlatform: mergeMaps(onPlatform, other.onPlatform,
Expand All @@ -263,16 +270,17 @@ class Metadata {

/// Returns a copy of [this] with the given fields changed.
Metadata change({PlatformSelector testOn, Timeout timeout, bool skip,
bool verboseTrace, String skipReason,
bool solo, bool verboseTrace, String skipReason,
Map<PlatformSelector, Metadata> onPlatform}) {
if (testOn == null) testOn = this.testOn;
if (timeout == null) timeout = this.timeout;
if (skip == null) skip = this.skip;
if (solo == null) solo = this.solo;
if (verboseTrace == null) verboseTrace = this.verboseTrace;
if (skipReason == null) skipReason = this.skipReason;
if (onPlatform == null) onPlatform = this.onPlatform;
return new Metadata(testOn: testOn, timeout: timeout, skip: skip,
verboseTrace: verboseTrace, skipReason: skipReason,
solo: solo, verboseTrace: verboseTrace, skipReason: skipReason,
onPlatform: onPlatform);
}

Expand Down Expand Up @@ -303,6 +311,7 @@ class Metadata {
'timeout': _serializeTimeout(timeout),
'skip': skip,
'skipReason': skipReason,
'solo': solo,
'verboseTrace': verboseTrace,
'tags': tags.toList(),
'onPlatform': serializedOnPlatform,
Expand Down
35 changes: 34 additions & 1 deletion lib/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ void test(description, body(),
{String testOn,
Timeout timeout,
skip,
solo,
tags,
Map<String, dynamic> onPlatform}) {
_declarer.test(description.toString(), body,
testOn: testOn,
timeout: timeout,
skip: skip,
solo: solo,
onPlatform: onPlatform,
tags: tags);

Expand All @@ -138,6 +140,21 @@ void test(description, body(),
return;
}

void solo_test(description, body(),
{String testOn,
Timeout timeout,
skip,
tags,
Map<String, dynamic> onPlatform}) {
test(description.toString(), body,
testOn: testOn,
timeout: timeout,
skip: skip,
solo: true,
onPlatform: onPlatform,
tags: tags);
}

/// Creates a group of tests.
///
/// A group's description (converted to a string) is included in the descriptions
Expand Down Expand Up @@ -189,10 +206,11 @@ void group(description, body(),
{String testOn,
Timeout timeout,
skip,
solo,
tags,
Map<String, dynamic> onPlatform}) {
_declarer.group(description.toString(), body,
testOn: testOn, timeout: timeout, skip: skip, tags: tags);
testOn: testOn, timeout: timeout, skip: skip, solo: solo, tags: tags);

// Force dart2js not to inline this function. We need it to be separate from
// `main()` in JS stack traces in order to properly determine the line and
Expand All @@ -201,6 +219,21 @@ void group(description, body(),
return;
}

void solo_group(description, body(),
{String testOn,
Timeout timeout,
skip,
tags,
Map<String, dynamic> onPlatform}) {
group(description, body,
testOn: testOn,
timeout: timeout,
skip: skip,
solo: true,
tags: tags,
onPlatform: onPlatform);
}

/// Registers a function to be run before tests.
///
/// This function will be called before each test is run. [callback] may be
Expand Down
Loading