File: shared.rb

package info (click to toggle)
ruby-test-unit-context 0.5.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 188 kB
  • sloc: ruby: 810; makefile: 2
file content (136 lines) | stat: -rw-r--r-- 3,859 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
module Test::Unit::Context
  module Shared
    
    # Share behavior among different contexts.
    # This creates a module (actually, a Module subclass) that is included 
    # using the +like+ method (or one of its aliases) provided by context (or 
    # +include+ if you know the module's constant name).
    #
    # ==== Examples
    #   
    #   shared "aasome-things" do
    #     test "does some thing" do
    #       # some-thing is awesome
    #     end
    #   end
    #
    #   like "aasome-things"
    #   # or 
    #   use "aasome-things"
    #
    #   share_as :client do
    #     test "is a client to our server" do
    #       # ...
    #     end
    #   end
    #
    #   like_a :client
    #   # or 
    #   uses "client"
    #
    def shared(name, &block)
      if ! name.is_a?(String) && ! name.is_a?(Symbol)
        raise ArgumentError, "use a String or Symbol as the name e.g. " + 
                             "`shared #{name.to_s.inspect} do ...`"  
      end
      const_name = Helpers.to_const_name(name.to_s)
      if Behavior.const_defined?(const_name)
        const = Behavior.const_get(const_name)
        if Behavior === const
          raise "duplicate shared definition with the name #{name.inspect} " <<
                 "found at #{caller.first} please provide an unique name"
        else
          raise "could not create a shared definition with the name " << 
                "#{name.inspect} as a constant #{Behavior.name}::#{const_name} " <<
                "already exists"
        end
      else
        behavior = Behavior.new(name, block)
        Behavior.const_set(const_name, behavior)
        # expose at current top-level test-case as a constant as well :
        test_case = self
        while test_case.is_a?(Test::Unit::Context)
          test_case = test_case.superclass
        end
        unless test_case.const_defined?(const_name)
          test_case.const_set(const_name, behavior)
        end
        behavior
      end
    end
    
    %w( share_as ).each { |m| alias_method m, :shared }
    
    # Pull in behavior shared by +shared+ or a module.  
    #
    # ==== Examples
    #   
    #   shared "awesome things" do
    #     test "does some thing" do
    #       # some-thing is awesome
    #     end
    #   end
    #
    #   like "awesome things"
    #
    #   module AwesomeThings
    #     # ...
    #   end
    #
    #   uses AwesomeThings
    #
    def like(shared_name)
      case shared_name
      when String, Symbol
        const_name = Helpers.to_const_name(shared_name.to_s)
        if Behavior.const_defined?(const_name)
          const = Behavior.const_get(const_name)
          if Behavior === const
            include const
          else
            raise "#{shared_name.inspect} does not resolve into a shared " << 
                   "behavior instance but to a #{const.inspect}"
          end
        else
          raise "shared behavior with name #{shared_name.inspect} not defined"
        end
      when Behavior, Module
        include shared_name
      else
        raise ArgumentError, "pass a String or Symbol as the name e.g. " +
                              "`like #{shared_name.to_s.inspect} do ...`"
      end
    end
    
    %w( like_a use uses ).each { |m| alias_method m, :like }
    
    # Returns all available shared definitions.
    def shared_definitions
      shareds = []
      constants.each do |name|
        const = const_get(name)
        if const.is_a?(Behavior)
          shareds << const
        end
      end
      shareds
    end
    
    class Behavior < Module
      
      attr_reader :shared_name
      
      def initialize(name, block)
        super()
        @shared_name = name
        @_block = block
      end

      def included(klass) # :nodoc:
        klass.class_eval(&@_block) # @_block.call
      end

    end
    
  end
end