├── Gemfile ├── spec ├── helper.rb ├── spec_expect.rb ├── spec_have.rb └── spec_be.rb ├── .ruby ├── .gitignore ├── lib ├── be.rb └── be │ ├── core_ext.rb │ ├── should.rb │ ├── errors.rb │ ├── expect.rb │ ├── delegator.rb │ ├── world.rb │ └── assertor.rb ├── .travis.yml ├── try └── spec_example.rb ├── .yardopts ├── Manifest.txt ├── .test ├── History.md ├── Assembly ├── Index.yml ├── License.txt ├── .index ├── README.md └── be.gemspec /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | gemspec 3 | -------------------------------------------------------------------------------- /spec/helper.rb: -------------------------------------------------------------------------------- 1 | require 'spectroscope' 2 | require 'be' 3 | -------------------------------------------------------------------------------- /.ruby: -------------------------------------------------------------------------------- 1 | ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-linux] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .reap/digest 2 | .yardoc 3 | doc 4 | log 5 | pkg 6 | tmp 7 | web 8 | -------------------------------------------------------------------------------- /lib/be.rb: -------------------------------------------------------------------------------- 1 | require 'be/expect' 2 | require 'be/should' 3 | 4 | class Object 5 | include Be::World 6 | end 7 | 8 | -------------------------------------------------------------------------------- /lib/be/core_ext.rb: -------------------------------------------------------------------------------- 1 | class Object 2 | 3 | def identical?(other) 4 | object_id == other.object_id 5 | end 6 | 7 | end 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | script: "bundle exec rubytest" 3 | rvm: 4 | - 1.9.2 5 | - 1.9.3 6 | - rbx-19mode 7 | - jruby-19mode 8 | 9 | -------------------------------------------------------------------------------- /try/spec_example.rb: -------------------------------------------------------------------------------- 1 | describe "example" do 2 | 3 | it "failed assertion" do 4 | [1,2,3].should have.size == 4 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title Behaviroial Expectations 2 | --output-dir doc 3 | --protected 4 | --private 5 | --readme README.md 6 | lib 7 | - 8 | [A-Z]*.* 9 | 10 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | #!mast .index .yardopts bin data demo lib spec test [A-Z]*.* 2 | .index 3 | .yardopts 4 | lib/be/assertor.rb 5 | lib/be/core_ext.rb 6 | lib/be/delegator.rb 7 | lib/be/errors.rb 8 | lib/be/kernel.rb 9 | lib/be/should.rb 10 | lib/be.rb 11 | spec/spec_be.rb 12 | spec/spec_have.rb 13 | Metadata.yml 14 | README.md 15 | History.md 16 | License.txt 17 | -------------------------------------------------------------------------------- /spec/spec_expect.rb: -------------------------------------------------------------------------------- 1 | describe "expect method" do 2 | 3 | it "should return an Be::Expector" do 4 | assert Be::Expector === expect(:foo) 5 | end 6 | 7 | it "should handle #to as an assertion" do 8 | expect(:foo).to be(:foo) 9 | end 10 | 11 | it "should handle #to_not as a refutation" do 12 | expect(:foo).to_not be(:bar) 13 | end 14 | 15 | end 16 | 17 | -------------------------------------------------------------------------------- /.test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | Test.run :default do |run| 4 | run.files << 'spec/spec_*.rb' 5 | 6 | require 'spectroscope' 7 | require 'be' 8 | end 9 | 10 | Test.run(:cov) do |run| 11 | run.files << 'spec/spec_*.rb' 12 | 13 | require 'simplecov' 14 | 15 | SimpleCov.start do 16 | require 'spectroscope' 17 | require 'be' 18 | 19 | coverage_dir 'log/coverage' 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | # Release History 2 | 3 | ## 0.2.0 / 2012-12-21 4 | 5 | This release adds expect-style notation and improves how 6 | the library can be loaded, either in total or in parts 7 | via `be/should` or `be/expect`. The later makes it possible 8 | to restraint the scope in which Be's methods available. 9 | 10 | Changes: 11 | 12 | * Add expect-style notation. 13 | * Make loading more versatile. 14 | 15 | 16 | ## 0.1.0 / 2012-02-28 17 | 18 | This is the first release of Be. 19 | 20 | Changes: 21 | 22 | * Happy Birthday! 23 | -------------------------------------------------------------------------------- /lib/be/should.rb: -------------------------------------------------------------------------------- 1 | require 'be/world' 2 | 3 | class Object 4 | public 5 | 6 | # 7 | # Object extension for asserting. 8 | # 9 | # 10.should be(10) 10 | # 11 | def should(assay) 12 | assay.to_assertor.assert!(self) 13 | end 14 | 15 | # 16 | # Object extension for refuting. 17 | # 18 | # 10.should_not be(5) 19 | # 20 | def should_not(assay) 21 | assay.to_assertor.refute!(self) 22 | end 23 | 24 | # 25 | # Alternative for #should_not. 26 | # 27 | alias :should! :should_not 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /lib/be/errors.rb: -------------------------------------------------------------------------------- 1 | module Be 2 | # Map assertion methods to the Errors that they should raise. 3 | # 4 | # In the future there is good chance this will depend on the Assay 5 | # library instead of defining our own error classes here. However 6 | # we'll wait until that library matures further before making that 7 | # leap. 8 | # 9 | ASSERTION_ERRORS = {} 10 | end 11 | 12 | class Exception 13 | # 14 | def self.be(name) 15 | Be::ASSERTION_ERRORS[name.to_sym] = self 16 | end 17 | end 18 | 19 | class TypeError 20 | be :instance_of? 21 | be :kind_of? 22 | end 23 | 24 | class EqualityError < StandardError 25 | be :== 26 | be :eql? 27 | be :equal? 28 | end 29 | 30 | -------------------------------------------------------------------------------- /lib/be/expect.rb: -------------------------------------------------------------------------------- 1 | require 'be/world' 2 | 3 | module Be 4 | 5 | # Encapsulate an expectation. 6 | # 7 | class Expector 8 | 9 | # Subject matter to the expectation. 10 | attr :subject 11 | 12 | def initialize(subject) 13 | @subject = subject 14 | end 15 | 16 | def to(assay) 17 | assay.to_assertor.assert!(subject) 18 | end 19 | 20 | def to_not(assay) 21 | assay.to_assertor.refute!(subject) 22 | end 23 | 24 | alias :not_to :to_not 25 | end 26 | 27 | module World 28 | private 29 | 30 | # Expect notation is similar to #should, but 31 | # doesn't need to extend the object. 32 | # 33 | # expect(10).to be(10) 34 | # 35 | def expect(object) 36 | Expector.new(object) 37 | end 38 | end 39 | 40 | end 41 | 42 | 43 | -------------------------------------------------------------------------------- /Assembly: -------------------------------------------------------------------------------- 1 | --- 2 | github: 3 | gh_pages: web 4 | 5 | gem: 6 | active: true 7 | 8 | dnote: 9 | title: Source Notes 10 | output: log/NOTES.rdoc 11 | 12 | yard: 13 | yardopts: true 14 | active: false 15 | 16 | #qed: 17 | # files : ~ 18 | # #exclude : ~ 19 | # #loadpath: ~ 20 | # #requires: ~ 21 | # #live : false 22 | # active : false 23 | 24 | #qedoc: 25 | # files : spec/ 26 | # output: QED.rdoc 27 | # active: false 28 | 29 | vclog: 30 | output: 31 | - log/changes.html 32 | - log/history.html 33 | active: false 34 | 35 | email: 36 | file : ~ 37 | subject: ~ 38 | mailto : 39 | - ruby-talk@ruby-lang.org 40 | - rubyworks-mailinglist@googlegroups.com 41 | from : <%= ENV['EMAIL_ACCOUNT'] %> 42 | server : <%= ENV['EMAIL_SERVER'] %> 43 | port : <%= ENV['EMAIL_PORT'] %> 44 | account: <%= ENV['EMAIL_ACCOUNT'] %> 45 | domain : <%= ENV['EMAIL_DOMAIN'] %> 46 | login : <%= ENV['EMAIL_LOGIN'] %> 47 | secure : <%= ENV['EMAIL_SECURE'] %> 48 | 49 | -------------------------------------------------------------------------------- /spec/spec_have.rb: -------------------------------------------------------------------------------- 1 | describe "have method" do 2 | 3 | it "should return a to have delegator" do 4 | assert Be::Delegator === have 5 | end 6 | 7 | it "with argument should return a HaveAssertor" do 8 | assert Be::Delegator === have('string') 9 | end 10 | 11 | it "should delegate and return an assertor" do 12 | assert Be::Delegator === have.anything 13 | end 14 | 15 | it "should defualt to #include? by default" do 16 | [1,2,3].should have(2) 17 | end 18 | 19 | it "should work to assert #size" do 20 | "string".should have(6).size 21 | "string".should have.size == 6 22 | end 23 | 24 | it "should work to refute #size" do 25 | "string".should_not have(7).size 26 | "string".should_not have.size == 7 27 | end 28 | 29 | it "should assert query methods" do 30 | "string".should have.include?('r') 31 | [1,2,3].should have.member?(1) 32 | end 33 | 34 | it "should handle method chains" do 35 | assert(Be::Delegator === have.size.to_s) 36 | 37 | "string".should have.size.to_s == '6' 38 | end 39 | 40 | end 41 | 42 | -------------------------------------------------------------------------------- /Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 3 | be 4 | 5 | version: 6 | 0.2.0 7 | 8 | title: 9 | Be 10 | 11 | summary: 12 | Behavior Expressive 13 | 14 | description: 15 | Behavioral Expectations is a fully versitle, light-weight and BRASS 16 | compliant assertions framework for Ruby. It utilizes an *assertor* design 17 | (*matchers* in RSpec terminology) which meshes well with BDD nomenclatures. 18 | 19 | requirements: 20 | - ansi 21 | - brass 22 | - detroit (build) 23 | - spectroscope (test) 24 | 25 | resources: 26 | home: http://rubyworks.github.com/be 27 | code: http://github.com/rubyworks/be 28 | docs: http://rubydoc.info/gems/be 29 | wiki: http://wiki.github.com/rubyworks/be 30 | bugs: http://github.com/rubyworks/be/issues 31 | mail: http://groups.google.com/group/rubyworks-mailinglist 32 | 33 | repositories: 34 | upstream: git://github.com/rubyworks/be.git 35 | 36 | organizations: 37 | - Rubyworks 38 | 39 | authors: 40 | - Trans 41 | 42 | copyrights: 43 | - (c) 2012 Rubyworks (BSD-2-Clause) 44 | 45 | created: 46 | 2012-02-27 47 | 48 | -------------------------------------------------------------------------------- /lib/be/delegator.rb: -------------------------------------------------------------------------------- 1 | module Be 2 | 3 | # Delegator acts as the go-between between the subjunctive call 4 | # and the Assertor. 5 | # 6 | class Delegator < BasicObject 7 | 8 | # 9 | # Initialize new Delegator. 10 | # 11 | def initialize(criteria={}) 12 | @criteria = criteria 13 | @messages = [] 14 | end 15 | 16 | # 17 | # Convert to Assertor. If `@messages` is empty then 18 | # defaults to calling method given by `criteria[:default]` 19 | # or `#==` failing that. 20 | # 21 | def to_assertor 22 | if @messages.empty? 23 | default = @criteria.delete(:default) || :== 24 | measure = @criteria.delete(:measure) 25 | messages = [[default, [measure], nil]] 26 | Assertor.new(messages, @criteria) 27 | else 28 | Assertor.new(@messages, @criteria) 29 | end 30 | end 31 | 32 | def method_missing(name, *args, &blk) 33 | @messages << [name, args, blk] 34 | self 35 | end 36 | 37 | def ==(other) 38 | @messages << [:==, [other], nil] 39 | self 40 | end 41 | 42 | def equal?(other) 43 | @messages << [:==, [other], nil] 44 | self 45 | end 46 | end 47 | 48 | end 49 | 50 | -------------------------------------------------------------------------------- /spec/spec_be.rb: -------------------------------------------------------------------------------- 1 | describe "be method" do 2 | 3 | it "should return a BeDelegator" do 4 | assert Be::Delegator === be 5 | end 6 | 7 | it "should return a BeDelegator with argument" do 8 | assert Be::Delegator === be('string') 9 | end 10 | 11 | it "should return a BeDelegator when method called" do 12 | assert Be::Delegator === be.anything 13 | end 14 | 15 | it "should return a BeDelegator with argument and method called" do 16 | assert Be::Delegator === be('something').anything 17 | end 18 | 19 | it "should work as assert equal when measure is given" do 20 | "string".should be('string') 21 | "string".should_not be('something else') 22 | end 23 | 24 | it "should assert equal when measure is geiven and method is called" do 25 | "string".should be('STRING').upcase 26 | end 27 | 28 | it "should assert queries, such as instance_of?" do 29 | "string".should be.instance_of?(String) 30 | "string".should_not be.instance_of?(Integer) 31 | end 32 | 33 | it "should assert operator queries such as ==" do 34 | "string".should be == 'string' 35 | end 36 | 37 | it "should assert for any lenght method chain" do 38 | "string".should be.upcase == 'STRING' 39 | end 40 | 41 | end 42 | 43 | -------------------------------------------------------------------------------- /lib/be/world.rb: -------------------------------------------------------------------------------- 1 | require 'brass' 2 | 3 | require 'be/core_ext' 4 | require 'be/errors' 5 | require 'be/assertor' 6 | require 'be/delegator' 7 | 8 | module Be 9 | 10 | # 11 | module World 12 | private 13 | 14 | # be 15 | # 16 | # "object".should be("object") 17 | # "object".should be.kind_of?(String) 18 | # 19 | def be(measure=:'n/a') 20 | criteria = { 21 | :compare => :==, 22 | :default => :==, 23 | :caller => caller 24 | } 25 | if measure != :'n/a' 26 | criteria[:measure] = measure 27 | end 28 | Be::Delegator.new(criteria) 29 | end 30 | 31 | # have 32 | # 33 | # "object".should have('bj')[1..2] 34 | # "object".should have.size == 6 35 | # 36 | # "object".should have.size 37 | # "object".should have.member?('j') 38 | # 39 | def have(measure=:'n/a') 40 | criteria = { 41 | :compare => :==, 42 | :default => :include?, 43 | :caller => caller 44 | } 45 | if measure != :'n/a' 46 | criteria[:measure] = measure 47 | end 48 | Be::Delegator.new(criteria) 49 | end 50 | 51 | # match 52 | # 53 | # TODO: How about #match which defaults to #=~ or #===? 54 | 55 | end 56 | 57 | end 58 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | BSD-2-Clause License 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | (http://spdx.org/licenses/BSD-2-Clause) 24 | 25 | -------------------------------------------------------------------------------- /.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Trans 8 | email: transfire@gmail.com 9 | organizations: 10 | - name: Rubyworks 11 | requirements: 12 | - name: ansi 13 | - name: brass 14 | - groups: 15 | - build 16 | development: true 17 | name: detroit 18 | - groups: 19 | - test 20 | development: true 21 | name: spectroscope 22 | conflicts: [] 23 | alternatives: [] 24 | resources: 25 | - type: home 26 | uri: http://rubyworks.github.com/be 27 | label: Homepage 28 | - type: code 29 | uri: http://github.com/rubyworks/be 30 | label: Source Code 31 | - type: docs 32 | uri: http://rubydoc.info/gems/be 33 | label: Documentation 34 | - type: wiki 35 | uri: http://wiki.github.com/rubyworks/be 36 | label: User Guide 37 | - type: bugs 38 | uri: http://github.com/rubyworks/be/issues 39 | label: Issue Tracker 40 | - type: mail 41 | uri: http://groups.google.com/group/rubyworks-mailinglist 42 | label: Mailing List 43 | repositories: 44 | - name: upstream 45 | scm: git 46 | uri: git://github.com/rubyworks/be.git 47 | categories: [] 48 | paths: 49 | load: 50 | - lib 51 | copyrights: 52 | - holder: Rubyworks 53 | year: '2012' 54 | license: BSD-2-Clause 55 | name: be 56 | title: Be 57 | version: 0.2.0 58 | summary: Behavior Expressive 59 | description: Behavioral Expectations is a fully versitle, light-weight and BRASS compliant 60 | assertions framework for Ruby. It utilizes an *assertor* design (*matchers* in RSpec 61 | terminology) which meshes well with BDD nomenclatures. 62 | created: '2012-02-27' 63 | date: '2012-12-21' 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Be - Behaviorial Expectations 2 | 3 | "Oh, Behave!" 4 | 5 | [Website](http://rubyworks.github.com.be) / 6 | [Report Issue](http://github.com/rubyworks/be/issues) / 7 | [Source Code](http://github.com/rubyworks/be) 8 | ( [![Build Status](https://secure.travis-ci.org/rubyworks/be.png)](http://travis-ci.org/rubyworks/be) ) 9 | 10 |
11 | 12 | Be is a versitle, light-weight and BRASS compliant assertions framework 13 | for Ruby. It utilizes an *assertor* design (known as *matchers* in RSpec terminology) 14 | which meshes well with BDD nomenclature. 15 | 16 | ## Instruction 17 | 18 | First you need to load the Be library into your test scope. There are two ways 19 | to do this. The first is the simplest and just entails loading `be`. 20 | 21 | require 'be' 22 | 23 | This loads the enitre library and includes `Be::World` into all scopes. The second 24 | approach provides more control over where the Be methods are added. To do this 25 | either require `be/should` or `be/expect` or both, and then include the 26 | `Be::World` module into the scope where the methods are to be available. 27 | 28 | require 'be/expect' 29 | 30 | module Cucumber::World 31 | include Be::World 32 | end 33 | 34 | After that it is simply a matter is using using `#should` or `#expect` with a target 35 | object, and passing it the reuslt of calling `#be` or `#have` with testable critera. 36 | 37 | object = "string" 38 | 39 | object.should be.instance_of?(String) 40 | object.should have(6).size 41 | 42 | expect(object).to be.instance_of?(String) 43 | expect(object).to have(6).size 44 | 45 | The only difference between `#be` and `#have` is the default criteria method that is 46 | implied if none is given. In the base of `#be` it is `#==`, for `#have` it is `#include?`. 47 | 48 | "abc".should be("abc") 49 | 50 | [:a,:b,:c].should have(:b) 51 | 52 | Be works on the principle of *assertors*, a type of functor, or higher-order 53 | message. In RSpec these are know as *matchers*. Be provides the methods `#should` 54 | and `#expect` that handle any object that converts to an assertor via a 55 | `#to_assertor` method. The `#be` and `#have` method returns just that, a `Be::Delegator` 56 | which orgnaizes all calls made against it to use as expectations in the `Be::Assertor`. 57 | 58 | 59 | ## Copyrights 60 | 61 | Be is copyrighted open source software. 62 | 63 | Copyright (c) 2012 Rubyworks 64 | 65 | Be is distributable in accordance with the **BSD-2-Clause** license. 66 | 67 | See **License.txt** for details. 68 | 69 | -------------------------------------------------------------------------------- /lib/be/assertor.rb: -------------------------------------------------------------------------------- 1 | module Be 2 | 3 | # An *assertor* is what RSpec calls a *matcher*. 4 | # 5 | class Assertor 6 | 7 | # 8 | def initialize(messages, criteria={}) 9 | @messages = messages 10 | @criteria = criteria 11 | @comparator = criteria[:compare] || :== 12 | end 13 | 14 | # 15 | def pass?(target) 16 | result = target 17 | @messages.each do |op, args, blk| 18 | result = result.__send__(op, *args, &blk) 19 | end 20 | 21 | if @criteria.key?(:measure) 22 | @criteria[:measure].__send__(@comparator, result) 23 | else 24 | result 25 | end 26 | end 27 | 28 | # 29 | def fail?(target) 30 | ! pass?(target) 31 | end 32 | 33 | # 34 | def assert!(target) 35 | handle(pass?(target), target) 36 | end 37 | 38 | # 39 | def refute!(target) 40 | handle(fail?(target), target) 41 | end 42 | 43 | alias_method :==, :pass? 44 | alias_method :!=, :fail? 45 | 46 | alias_method :=~, :assert! 47 | alias_method :!~, :refute! 48 | 49 | alias_method :===, :assert! 50 | 51 | private 52 | 53 | # 54 | # 55 | # 56 | def handle(result, target) 57 | if result 58 | increment_passing 59 | else 60 | increment_failing 61 | 62 | error_class = Be::ASSERTION_ERRORS[@operator] || StandardError 63 | 64 | msg = assert_message(target) #, @operator, @arguments) 65 | err = error_class.new(msg) 66 | err.set_backtrace(@criteria[:caller] || caller[2..-1]) 67 | err.set_assertion(true) 68 | raise err 69 | end 70 | end 71 | 72 | # 73 | # Produce an error message. 74 | # 75 | def assert_message(target) 76 | #"#{target.inspect} #{@operator} #{@arguemnts.map{ |x| x.inspect }}" 77 | 78 | s = "b" 79 | r = target 80 | 81 | sigs = [] 82 | 83 | @messages.each do |meth, args, blk| 84 | vars = [] 85 | list = [] 86 | 87 | args.each do |a| 88 | vars << s 89 | list << "#{s}) " + a.inspect 90 | s = s.succ 91 | end 92 | 93 | sigs << [meth, vars, list] 94 | end 95 | 96 | msgs = [] 97 | vest = ["a) #{r.inspect}"] 98 | sigs.each do |meth, vars, list| 99 | msgs << "#{meth}(#{vars.join(', ')})" 100 | vest << list.join("\n") unless list.empty? 101 | end 102 | 103 | "a." + msgs.join(".") + "\n" + vest.join("\n") 104 | end 105 | 106 | # 107 | # 108 | # 109 | def refute_message(target) 110 | "! " + assert_message(target) 111 | end 112 | 113 | # 114 | # Increment BRASS standard assertion counts for passing assertion. 115 | # 116 | def increment_passing 117 | $ASSERTION_COUNTS[:total] += 1 118 | $ASSERTION_COUNTS[:pass] += 1 119 | end 120 | 121 | # 122 | # Increment BRASS standard assertion counts for failing assertion. 123 | # 124 | def increment_failing 125 | $ASSERTION_COUNTS[:total] += 1 126 | $ASSERTION_COUNTS[:fail] += 1 127 | end 128 | 129 | public 130 | 131 | # The following methods allow these to work as RSpec matchers. 132 | 133 | # For RSpec matcher compatability. 134 | alias_method :matches?, :pass? 135 | 136 | # For RSpec matcher compatability. 137 | alias_method :does_not_match?, :fail? 138 | 139 | # For RSpec matcher compatability. 140 | alias_method :failure_message_for_should, :assert_message 141 | 142 | # For RSpec matcher compatability. 143 | alias_method :failure_message_for_should_not, :refute_message 144 | 145 | end 146 | 147 | end 148 | -------------------------------------------------------------------------------- /be.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'yaml' 4 | require 'pathname' 5 | 6 | module Indexer 7 | 8 | # Convert index data into a gemspec. 9 | # 10 | # Notes: 11 | # * Assumes all executables are in bin/. 12 | # * Does not yet handle default_executable setting. 13 | # * Does not yet handle platform setting. 14 | # * Does not yet handle required_ruby_version. 15 | # * Support for rdoc entries is weak. 16 | # 17 | class GemspecExporter 18 | 19 | # File globs to include in package (unless manifest file exists). 20 | FILES = ".index .ruby .yardopts alt bin ext lib man spec test [A-Z]*.*" unless defined?(FILES) 21 | 22 | # File globs to omit. 23 | OMIT = "Config.rb" unless defined?(OMIT) 24 | 25 | # Standard file patterns. 26 | PATTERNS = { 27 | :root => '{.index,Gemfile}', 28 | :bin => 'bin/*', 29 | :lib => 'lib/{**/}*', #.rb', 30 | :ext => 'ext/{**/}extconf.rb', 31 | :doc => '*.{txt,rdoc,md,markdown,tt,textile}', 32 | :test => '{test,spec}/{**/}*.rb' 33 | } unless defined?(PATTERNS) 34 | 35 | # For which revision of indexer spec is this converter intended? 36 | REVISION = 2013 unless defined?(REVISION) 37 | 38 | # 39 | def self.gemspec 40 | new.to_gemspec 41 | end 42 | 43 | # 44 | attr :metadata 45 | 46 | # 47 | def initialize(metadata=nil) 48 | @root_check = false 49 | 50 | if metadata 51 | root_dir = metadata.delete(:root) 52 | if root_dir 53 | @root = root_dir 54 | @root_check = true 55 | end 56 | metadata = nil if metadata.empty? 57 | end 58 | 59 | @metadata = metadata || YAML.load_file(root + '.index') 60 | 61 | if @metadata['revision'].to_i != REVISION 62 | warn "This gemspec exporter was not designed for this revision of index metadata." 63 | end 64 | end 65 | 66 | # 67 | def has_root? 68 | root ? true : false 69 | end 70 | 71 | # 72 | def root 73 | return @root if @root || @root_check 74 | @root_check = true 75 | @root = find_root 76 | end 77 | 78 | # 79 | def manifest 80 | return nil unless root 81 | @manifest ||= Dir.glob(root + 'manifest{,.txt}', File::FNM_CASEFOLD).first 82 | end 83 | 84 | # 85 | def scm 86 | return nil unless root 87 | @scm ||= %w{git hg}.find{ |m| (root + ".#{m}").directory? }.to_sym 88 | end 89 | 90 | # 91 | def files 92 | return [] unless root 93 | @files ||= \ 94 | if manifest 95 | File.readlines(manifest). 96 | map{ |line| line.strip }. 97 | reject{ |line| line.empty? || line[0,1] == '#' } 98 | else 99 | list = [] 100 | Dir.chdir(root) do 101 | FILES.split(/\s+/).each do |pattern| 102 | list.concat(glob(pattern)) 103 | end 104 | OMIT.split(/\s+/).each do |pattern| 105 | list = list - glob(pattern) 106 | end 107 | end 108 | list 109 | end.select{ |path| File.file?(path) }.uniq 110 | end 111 | 112 | # 113 | def glob_files(pattern) 114 | return [] unless root 115 | Dir.chdir(root) do 116 | Dir.glob(pattern).select do |path| 117 | File.file?(path) && files.include?(path) 118 | end 119 | end 120 | end 121 | 122 | def patterns 123 | PATTERNS 124 | end 125 | 126 | def executables 127 | @executables ||= \ 128 | glob_files(patterns[:bin]).map do |path| 129 | File.basename(path) 130 | end 131 | end 132 | 133 | def extensions 134 | @extensions ||= \ 135 | glob_files(patterns[:ext]).map do |path| 136 | File.basename(path) 137 | end 138 | end 139 | 140 | def name 141 | metadata['name'] || metadata['title'].downcase.gsub(/\W+/,'_') 142 | end 143 | 144 | def homepage 145 | page = ( 146 | metadata['resources'].find{ |r| r['type'] =~ /^home/i } || 147 | metadata['resources'].find{ |r| r['name'] =~ /^home/i } || 148 | metadata['resources'].find{ |r| r['name'] =~ /^web/i } 149 | ) 150 | page ? page['uri'] : false 151 | end 152 | 153 | def licenses 154 | metadata['copyrights'].map{ |c| c['license'] }.compact 155 | end 156 | 157 | def require_paths 158 | metadata['load_path'] || ['lib'] 159 | end 160 | 161 | # 162 | # Convert to gemnspec. 163 | # 164 | def to_gemspec 165 | if has_root? 166 | Gem::Specification.new do |gemspec| 167 | to_gemspec_data(gemspec) 168 | to_gemspec_paths(gemspec) 169 | end 170 | else 171 | Gem::Specification.new do |gemspec| 172 | to_gemspec_data(gemspec) 173 | to_gemspec_paths(gemspec) 174 | end 175 | end 176 | end 177 | 178 | # 179 | # Convert pure data settings. 180 | # 181 | def to_gemspec_data(gemspec) 182 | gemspec.name = name 183 | gemspec.version = metadata['version'] 184 | gemspec.summary = metadata['summary'] 185 | gemspec.description = metadata['description'] 186 | 187 | metadata['authors'].each do |author| 188 | gemspec.authors << author['name'] 189 | 190 | if author.has_key?('email') 191 | if gemspec.email 192 | gemspec.email << author['email'] 193 | else 194 | gemspec.email = [author['email']] 195 | end 196 | end 197 | end 198 | 199 | gemspec.licenses = licenses 200 | 201 | requirements = metadata['requirements'] || [] 202 | requirements.each do |req| 203 | next if req['optional'] 204 | next if req['external'] 205 | 206 | name = req['name'] 207 | groups = req['groups'] || [] 208 | 209 | version = gemify_version(req['version']) 210 | 211 | if groups.empty? or groups.include?('runtime') 212 | # populate runtime dependencies 213 | if gemspec.respond_to?(:add_runtime_dependency) 214 | gemspec.add_runtime_dependency(name,*version) 215 | else 216 | gemspec.add_dependency(name,*version) 217 | end 218 | else 219 | # populate development dependencies 220 | if gemspec.respond_to?(:add_development_dependency) 221 | gemspec.add_development_dependency(name,*version) 222 | else 223 | gemspec.add_dependency(name,*version) 224 | end 225 | end 226 | end 227 | 228 | # convert external dependencies into gemspec requirements 229 | requirements.each do |req| 230 | next unless req['external'] 231 | gemspec.requirements << ("%s-%s" % req.values_at('name', 'version')) 232 | end 233 | 234 | gemspec.homepage = homepage 235 | gemspec.require_paths = require_paths 236 | gemspec.post_install_message = metadata['install_message'] 237 | end 238 | 239 | # 240 | # Set gemspec settings that require a root directory path. 241 | # 242 | def to_gemspec_paths(gemspec) 243 | gemspec.files = files 244 | gemspec.extensions = extensions 245 | gemspec.executables = executables 246 | 247 | if Gem::VERSION < '1.7.' 248 | gemspec.default_executable = gemspec.executables.first 249 | end 250 | 251 | gemspec.test_files = glob_files(patterns[:test]) 252 | 253 | unless gemspec.files.include?('.document') 254 | gemspec.extra_rdoc_files = glob_files(patterns[:doc]) 255 | end 256 | end 257 | 258 | # 259 | # Return a copy of this file. This is used to generate a local 260 | # .gemspec file that can automatically read the index file. 261 | # 262 | def self.source_code 263 | File.read(__FILE__) 264 | end 265 | 266 | private 267 | 268 | def find_root 269 | root_files = patterns[:root] 270 | if Dir.glob(root_files).first 271 | Pathname.new(Dir.pwd) 272 | elsif Dir.glob("../#{ROOT}").first 273 | Pathname.new(Dir.pwd).parent 274 | else 275 | #raise "Can't find root of project containing `#{root_files}'." 276 | warn "Can't find root of project containing `#{root_files}'." 277 | nil 278 | end 279 | end 280 | 281 | def glob(pattern) 282 | if File.directory?(pattern) 283 | Dir.glob(File.join(pattern, '**', '*')) 284 | else 285 | Dir.glob(pattern) 286 | end 287 | end 288 | 289 | def gemify_version(version) 290 | case version 291 | when /^(.*?)\+$/ 292 | ">= #{$1}" 293 | when /^(.*?)\-$/ 294 | "< #{$1}" 295 | when /^(.*?)\~$/ 296 | "~> #{$1}" 297 | else 298 | version 299 | end 300 | end 301 | 302 | end 303 | 304 | end 305 | 306 | Indexer::GemspecExporter.gemspec --------------------------------------------------------------------------------