/lib/extensions/rhospec/rhospec.rb

https://github.com/raulvejar/rhodes · Ruby · 466 lines · 367 code · 93 blank · 6 comment · 23 complexity · 4854e83cd95866ff4dda4382ece83c14 MD5 · raw file

  1. require 'version'
  2. class MSpecScript
  3. # Returns the config object. Maintained at the class
  4. # level to easily enable simple config files. See the
  5. # class method +set+.
  6. def self.config
  7. @config ||= {
  8. }
  9. end
  10. def config
  11. MSpecScript.config
  12. end
  13. end
  14. class RhoSpecModule
  15. attr_accessor :before, :after, :tests, :spec_name
  16. def initialize(spec_name, spec_body)
  17. @before = {}
  18. @after = {}
  19. @tests = {}
  20. @env = Object.new
  21. @spec_name = spec_name
  22. @spec_body = spec_body
  23. end
  24. def run_spec
  25. setting_str = $spec_settings.length()>0 ? ";#{$spec_settings}" : ""
  26. puts "TEST: #{@spec_name}" + setting_str
  27. @env.instance_eval(&@spec_body) if @spec_body
  28. end
  29. def run_test(test_body)
  30. @env.instance_eval(&test_body) if test_body
  31. end
  32. end
  33. class MSpec
  34. VERSION = "RhoSpec 1.0"
  35. attr_reader :exc_count, :count, :errorMessages, :code, :is_network_available
  36. @@spec_modules = []
  37. @@spec_index = 0
  38. @@spec_files = []
  39. @@instance = nil
  40. def self.exit_code
  41. @@instance.code
  42. end
  43. def self.exc_count
  44. @@instance.exc_count
  45. end
  46. def self.count
  47. @@instance.count
  48. end
  49. def self.errorMessages
  50. @@instance.errorMessages
  51. end
  52. def self.is_network_available
  53. @@instance.is_network_available
  54. end
  55. def self.current
  56. @@spec_modules[@@spec_index]
  57. end
  58. def self.register_files(spec_files)
  59. @@spec_files = spec_files
  60. end
  61. def self.process
  62. @@instance = MSpec.new
  63. @@instance.start
  64. end
  65. def start
  66. @exc_count = 0
  67. @count = 0
  68. @errorMessages = ""
  69. @is_network_available = System.get_property('has_network')
  70. $is_network_available = @is_network_available
  71. @@spec_files.each do |spec_file|
  72. if spec_file.is_a?(Array)
  73. run_spec(spec_file[0], spec_file[1])
  74. else
  75. run_spec(spec_file, [{}])
  76. end
  77. end
  78. @code = @exc_count > 0 ? 1 : 0
  79. end
  80. def self.describe(mod, msg=nil, options=nil, &block)
  81. @@spec_modules << RhoSpecModule.new(mod, block)
  82. end
  83. def run_test(spec_name,test_name, &block)
  84. begin
  85. @count += 1
  86. puts " - #{test_name}"
  87. yield if block_given?
  88. rescue Exception => e
  89. @exc_count += 1
  90. ntrace_index = 2 #MSpec.current && MSpec.current.tests.size() > 0 ? 2 : 1
  91. @errorMessages += "<br/>FAIL: '#{spec_name}:#{test_name}; #{$spec_settings}' failed: Error: #{e}\n" +
  92. "#{e.backtrace[ntrace_index]}" if e.backtrace && e.backtrace.length > 0
  93. puts "FAIL: '#{spec_name}:#{test_name}; #{$spec_settings}' failed: Error: #{e}\n" +
  94. "#{e.backtrace[ntrace_index]}" if e.backtrace && e.backtrace.length > 0
  95. e.backtrace.each do |item|
  96. puts item
  97. end
  98. end
  99. end
  100. def run_specs
  101. @@spec_modules.each do |spec_module|
  102. spec_module.run_spec
  103. spec_module.run_test(spec_module.before[:all])
  104. spec_module.tests.each do |test_name, body|
  105. spec_module.run_test(spec_module.before[:each])
  106. @@spec_name = spec_module.spec_name
  107. run_test(@@spec_name, test_name){spec_module.run_test(body)}
  108. spec_module.run_test(spec_module.after[:each])
  109. end
  110. spec_module.run_test(spec_module.after[:all])
  111. @@spec_index += 1
  112. end
  113. end
  114. def run_spec(spec_file, spec_settings)
  115. @@spec_name = ""
  116. begin
  117. @@spec_modules = []
  118. require spec_file
  119. spec_settings.each do |settings|
  120. $spec_settings = settings
  121. @@spec_index = 0
  122. run_specs
  123. end
  124. rescue Exception => e
  125. @exc_count += 1
  126. puts "Test '#{@@spec_name}; #{$spec_settings}' FAIL: Error: #{e}"
  127. e.backtrace.each do |item|
  128. puts item
  129. end
  130. end
  131. end
  132. end
  133. class Object
  134. def before(at=:each, &block)
  135. MSpec.current.before[ at ] = block
  136. end
  137. def after(at=:each, &block)
  138. MSpec.current.after[ at ] = block
  139. end
  140. def describe(mod, msg=nil, options=nil, &block)
  141. MSpec.describe mod, msg, &block
  142. end
  143. def it(msg, &block)
  144. MSpec.current.tests[ msg ] = block
  145. end
  146. def it_should_behave_like(desc)
  147. raise "it_should_behave_like not implemented"
  148. end
  149. alias_method :context, :describe
  150. alias_method :specify, :it
  151. end
  152. class PositiveOperatorMatcher
  153. def initialize(actual)
  154. @actual = actual
  155. end
  156. def ==(expected)
  157. unless @actual == expected
  158. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  159. "to equal #{expected.pretty_inspect}")
  160. end
  161. end
  162. def <(expected)
  163. unless @actual < expected
  164. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  165. "to be less than #{expected.pretty_inspect}")
  166. end
  167. end
  168. def <=(expected)
  169. unless @actual <= expected
  170. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  171. "to be less than or equal to #{expected.pretty_inspect}")
  172. end
  173. end
  174. def >(expected)
  175. unless @actual > expected
  176. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  177. "to be greater than #{expected.pretty_inspect}")
  178. end
  179. end
  180. def >=(expected)
  181. unless @actual >= expected
  182. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  183. "to be greater than or equal to #{expected.pretty_inspect}")
  184. end
  185. end
  186. def =~(expected)
  187. unless @actual =~ expected
  188. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  189. "to match #{expected.pretty_inspect}")
  190. end
  191. end
  192. end
  193. class BeNilMatcher
  194. def matches?(actual)
  195. @actual = actual
  196. @actual.nil?
  197. end
  198. def failure_message
  199. ["Expected #{@actual.inspect}", "to be nil"]
  200. end
  201. def negative_failure_message
  202. ["Expected #{@actual.inspect}", "not to be nil"]
  203. end
  204. end
  205. class Expectation
  206. def self.fail_with(msg, msg1)
  207. raise msg+ " " + msg1
  208. end
  209. end
  210. module Kernel
  211. # returns a pretty printed object as a string.
  212. def pretty_inspect
  213. inspect
  214. end
  215. end
  216. class NegativeOperatorMatcher
  217. def initialize(actual)
  218. @actual = actual
  219. end
  220. def ==(expected)
  221. if @actual == expected
  222. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  223. "not to equal #{expected.pretty_inspect}")
  224. end
  225. end
  226. def <(expected)
  227. if @actual < expected
  228. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  229. "not to be less than #{expected.pretty_inspect}")
  230. end
  231. end
  232. def <=(expected)
  233. if @actual <= expected
  234. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  235. "not to be less than or equal to #{expected.pretty_inspect}")
  236. end
  237. end
  238. def >(expected)
  239. if @actual > expected
  240. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  241. "not to be greater than #{expected.pretty_inspect}")
  242. end
  243. end
  244. def >=(expected)
  245. if @actual >= expected
  246. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  247. "not to be greater than or equal to #{expected.pretty_inspect}")
  248. end
  249. end
  250. def =~(expected)
  251. if @actual =~ expected
  252. Expectation.fail_with("Expected #{@actual.pretty_inspect}",
  253. "not to match #{expected.pretty_inspect}")
  254. end
  255. end
  256. end
  257. class BeTrueMatcher
  258. def matches?(actual)
  259. @actual = actual
  260. @actual == true
  261. end
  262. def failure_message
  263. ["Expected #{@actual.inspect}", "to be true"]
  264. end
  265. def negative_failure_message
  266. ["Expected #{@actual.inspect}", "not to be true"]
  267. end
  268. end
  269. class BeFalseMatcher
  270. def matches?(actual)
  271. @actual = actual
  272. @actual == false
  273. end
  274. def failure_message
  275. ["Expected #{@actual.inspect}", "to be false"]
  276. end
  277. def negative_failure_message
  278. ["Expected #{@actual.inspect}", "not to be false"]
  279. end
  280. end
  281. class RaiseErrorMatcher
  282. def initialize(exception, message, &block)
  283. @exception = exception
  284. @message = message
  285. @block = block
  286. end
  287. def matches?(proc)
  288. proc.call
  289. return false
  290. rescue Exception => err
  291. @actual = err
  292. return false unless @exception === @actual
  293. if @message then
  294. case @message
  295. when String then
  296. return false if @message != @actual.message
  297. when Regexp then
  298. return false if @message !~ @actual.message
  299. end
  300. end
  301. @block[@actual] if @block
  302. return true
  303. end
  304. def failure_message
  305. message = ["Expected #{@exception}#{%[ (#{@message})] if @message}"]
  306. if @actual then
  307. message << "but got #{@actual.class}#{%[ (#{@actual.message})] if @actual.message}"
  308. else
  309. message << "but no exception was raised"
  310. end
  311. message
  312. end
  313. def negative_failure_message
  314. ["Expected to not get #{@exception}#{%[ (#{@message})] if @message}", ""]
  315. end
  316. end
  317. class EqualMatcher
  318. def initialize(expected)
  319. @expected = expected
  320. end
  321. def matches?(actual)
  322. @actual = actual
  323. @actual.equal?(@expected)
  324. end
  325. def failure_message
  326. ["Expected #{@actual.pretty_inspect}",
  327. "to be identical to #{@expected.pretty_inspect}"]
  328. end
  329. def negative_failure_message
  330. ["Expected #{@actual.pretty_inspect}",
  331. "not to be identical to #{@expected.pretty_inspect}"]
  332. end
  333. end
  334. class Object
  335. def should(matcher=nil)
  336. if matcher
  337. unless matcher.matches?(self)
  338. Expectation.fail_with(*matcher.failure_message)
  339. end
  340. else
  341. PositiveOperatorMatcher.new(self)
  342. #raise "Expected '#{matcher.inspect.to_s}' equal to nil" if self != nil
  343. end
  344. end
  345. def should_not(matcher=nil)
  346. if matcher
  347. if matcher.matches?(self)
  348. Expectation.fail_with(*matcher.negative_failure_message)
  349. end
  350. else
  351. #raise "Expected '#{self.inspect.to_s}' not equal to nil" if self == nil
  352. NegativeOperatorMatcher.new(self)
  353. end
  354. end
  355. def be_nil
  356. BeNilMatcher.new
  357. end
  358. def be_true
  359. BeTrueMatcher.new
  360. end
  361. def be_false
  362. BeFalseMatcher.new
  363. end
  364. def equal(expected)
  365. EqualMatcher.new(expected)
  366. end
  367. def raise_error(exception=Exception, message=nil, &block)
  368. RaiseErrorMatcher.new(exception, message, &block)
  369. end
  370. def ruby_version_is(*args)
  371. yield
  372. end
  373. end