Skip to content

Commit

Permalink
Introduced better test registering:
Browse files Browse the repository at this point in the history
- Removed Type.test() method for detached tests registering.
- Added handling for inline group tests.
- Added handling for test factories defined inside a group.
- Changed simple name validation - test name can be unselectable but cannot contain dots.
- Changed selection tree generation - now only groups are visible for selection.
  • Loading branch information
marek-kuzora committed Feb 21, 2012
1 parent 0944f0b commit 1939d51
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 104 deletions.
113 changes: 101 additions & 12 deletions source/group.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@



# Reserved group properties. Properties defined below will be used to
# define group parameters, whereas all other group properties will be
# used to create tests.
RESERVED = [
'after', 'after_each' , 'before', 'before_each' ,
'envs', 'generators', 'min_arg', 'run', 'scenario'
]


return class Group extends Node

constructor: (name, parent, type, raw = {}) ->
Expand All @@ -14,40 +23,104 @@ return class Group extends Node
# Collection of group nodes.
@nodes = []

# Assert the simple name is selectable.
if not @_is_selectable(@_simple)
throw new Error "Simple name '#{@_simple}' is not selectable."

# Update the selection tree.
parent.get_selection_tree()[@_simple] = @get_selection_tree()

# Create tests from all other not RESERVED properties.
@_create_tests(raw)


#
# Returns true if the given name matches variable regexp and
# therefore is selectable.
#
# @param name {String}
# @return {Boolean}
#
_is_selectable: (name) ->
return regexp().VARIABLE.test(name)


#
# Creates group tests from all not RESERVED properties.
# If raw.generators is defined, generates additional tests using
# factories for each provided argument.
#
# @param raw {Object}
#
_create_tests: (raw) ->

# Register inline tests provided in raw hash.
for name, test in raw when RESERVED.indexOf(k) is -1
@register_test(name, test)

# Register tests from factories generated using provided arguments.
for generator in raw.generators
for argument in generator.args

# Factory must always return a hash of tests.
for name, test of generator.factory(argument)
@register_test(name, test)


#
# Creates and adds a new group child node. Attaches child node
# selection tree into the group selection tree. Throws an error
# if the name is duplicated with any of the existing group nodes.
#
# @param type {Class} node class type.
# @param name {String} node name.
# @param ttype {String} tests type name.
# @param raw {Object} node definition.
# @param name {String} group name.
# @param raw {Object} group definition.
#
# @return {Node}
# @return {Group}
#
add: (type, name, ttype, raw) ->

register_group: (name, raw) ->
# Assert the name is unique.
for n in @nodes when n.name is name
throw new Error "Node #{name} already exists"

# Create new node and push it as a group child.
@nodes.push(n = new type(name, @, ttype, raw))
@nodes.push(group = new Group(name, @, @_type, raw))
return group

# Update the selection tree.
@get_selection_tree()[n.get_simple_name()] = n.get_selection_tree()

return n
#
# Creates and adds a new test child node. Accepts raw as function as
# a shortcut definition. Throws an error if the name is duplicated
# with any of the existing group nodes.
#
# @param name {String} test name.
# @param raw {Object} test definition.
#
# @return {Test}
#
register_test: (name, raw) ->

# Expands the test name.
name = @get_child_prefix + name

# Expands the shortcut test definition.
if typeof raw is 'function'
raw = run: raw

# Assert the name is unique.
for n in @nodes when n.name is name
throw new Error "Node #{name} already exists"

# Create new node and push it as a group child.
@nodes.push(test = new Test(name, @, @_type, raw))
return test


#
# Returns node with specified name. Throws an error if no node
# is found.
#
# @param name {String} simple node name.
#
# @return {Node}
#
get: (name) ->
Expand Down Expand Up @@ -84,3 +157,19 @@ return class Group extends Node
#
get_child_prefix: ->
return if @name is '' then @name else @name + '.'


#
# Returns root of the node selection tree. If the node is a group,
# it will use its root to attach child nodes selection trees by
# their simple names.
#
# @return {->} node selection tree root.
#
get_selection_tree: ->

# Assign fully qualified node name.
name = if @name then @_type + '.' + @name else @_type

# Assign the selection function.
return @_selection ?= -> context().select(name)
53 changes: 2 additions & 51 deletions source/node.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,17 @@ return class Node
#
# @param name {String} node full name.
# @param parent {Node} node parent.
# @param type {String} node type name.
# @param raw {Object} node definition.
#
constructor: (@name, @parent, @_type, raw) ->

# Node simple name.
# Node simple name.
@_simple = @name.substr(@parent.get_child_prefix().length)

# Assert the simple name is selectable.
if not @_is_selectable(@_simple)
throw new Error "Simple name '#{@_simple}' is not selectable"

# Node display name.
@_display = raw.display || @name

# Collection of preloaded modules.
@_envs = raw.envs || []

# Collection of node dependences (in qa).
@_dpds = raw.dependences || []

# Minimal number of times to run (in pfc).
@_min_arg = raw.min_arg || 0

Expand All @@ -47,46 +38,6 @@ return class Node
@_after_each = raw.after_each || (->)


#
# Returns true if the given name matches variable regexp
# and therefore is selectable.
#
# @param name {String}
# @return {Boolean}
#
_is_selectable: (name) ->
return regexp().VARIABLE.test(name)


#
# Returns the node simple name. Simple name is assured to be
# selectable, that means the client will be able to treat it as
# a normal property when selecting the tests via selection tree.
#
# @return {String}
#
get_simple_name: ->
return @_simple


#
# Returns root of the node selection tree. If the node is a group,
# it will use its root to attach child nodes selection trees by
# their simple names.
#
# @return {->} node selection tree root.
#
get_selection_tree: ->

# Assign fully qualified node name.
name = if @name then @_type + '.' + @name else @_type

# Assign the selection function.
return @_selection ?= ->
context().select(name)



# draft
preload_envs: ->
F.run(env) for env in @_envs
Expand Down
12 changes: 12 additions & 0 deletions source/runner.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
return class Runner

run: (tests) ->

_run_loop: ->


# Run uruchamia podstawowe testy - musi najpierw zbudowac tablice swoich test-cases: to musi byc tak zrobione, aby np mogl latwo wsadzic testy, ktore wykonuja measure!
#
# Jak chce takie test-cases zbudowac? O ile dla powtarzanych testow moge powtorzyc instancje testu, o tyle nie wiem jak measure tam wsadzic :/
#
# Musze trzymac informacje o aktualnym tescie D:
4 changes: 4 additions & 0 deletions source/test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ return class Test extends Node
if not F.is_function(@_run)
throw new Error "Run method not found: #{@name}"

# Assert the simple name does not contain dot character.
if @_simple.indexOf('.') isnt -1
throw new Error "Simple name '#{@_simple}' contains dot character."


#
# Stub method that returns the node as its tests. Exists in order to
Expand Down
53 changes: 12 additions & 41 deletions source/type.coffee
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#
# @require:
# Test: fest/test
# Group: fest/group
#

Expand All @@ -15,7 +14,7 @@ return class Type
constructor: (@name, @runner) ->

# Root group of the groups hierarchy tree.
@_root = new Group('')
@_root = new Group('', undefined, @name)

# Last referenced group. Default parent when adding test cases.
@_last_group = @_root
Expand All @@ -29,40 +28,32 @@ return class Type


#
# Registers a group under the given name.
# Registers a scenario group under the given name.
#
# @param name {String} group name.
# @param raw {Object} group definition.
#
group: (name, raw) ->

# From the group name: if it's absolute & its full name.
absolute = @_is_group_absolute(name)
full_name = @_resolve_group_name(name, absolute)

# Retrieve the group parent & create the group inside.
parent = @get(full_name, true)
group = parent.add(Group, full_name, @name, raw)

# Set group as the last group & as node group if it's absolute.
@_last_group = group
@_node_group = group if absolute
scenario: (name, raw = {}) ->
raw.scenario = true
@group(name, raw)


#
# References a group with the given name.
# Registers a group under the given name.
#
# @param name {String} group name.
# @param raw {Object} group definition.
#
use: (name) ->
group: (name, raw) ->

# From the group name: if it's absolute & its full name.
absolute = @_is_group_absolute(name)
full_name = @_resolve_group_name(name, absolute)

# Retrieves the group matching the given full_name.
group = @get(full_name, false)

# Retrieve the group parent & create the group inside.
parent = @get(full_name, true)
group = parent.register_group(full_name, raw)

# Set group as the last group & as node group if it's absolute.
@_last_group = group
@_node_group = group if absolute
Expand Down Expand Up @@ -98,26 +89,6 @@ return class Type
return @_node_group.get_child_prefix() + name


#
# Registers a test under the latest referenced group.
#
# @param name {String} test name.
# @param raw {Object} test definition.
#
test: (name, raw) ->
@_last_group.add(Test, @_resolve_test_name(name), @name, raw)


#
# Returns full name from the given test name. The test is always a
# child of the last referenced group.
#
# @param name {String} test name.
#
_resolve_test_name: (name) ->
return @_last_group.get_child_prefix() + name


#
# Returns the node corresponding to the given name. Returns parent
# of that node if parent parameter was set to true.
Expand Down

0 comments on commit 1939d51

Please sign in to comment.