-
Notifications
You must be signed in to change notification settings - Fork 1
Provides a clean, easy way to check method arguments at runtime.
License
justinwiley/higher-expectations
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
= higher_expectations * http://higher-expect.rubyforge.org == DESCRIPTION: Provides an easy and quick way to make sure method arguments are what you expect them to be. You want to make sure that methods explode if they are given inappropriate inputs, but you don't want to deal with a complete design-by-contract implementation like RDBC. Please note that this is nothing like a formal design-by-contract in any number of important ways. It provides something -like- the "obligations" component of DBC. Writing explicit exception checking is tiring, redundant and error prone: def calc_sunrise(day, month, year, latitude, longitude, planet) raise Exception.new("day should be numeric and in the range of 1-32) unless day.kind_of?(Numeric) && day > 0 && day < 32 ...etc. etc. ... end Higher expectations provides an easy and human readable alternative: def calc_sunrise(day, month, year) has_expectations(day, month) day.must_not_be(Numeric).and_must_be_in_range(0..5) month.must_be(Numeric) ...do other critical work below... end == FEATURES/PROBLEMS: * Please note that this is alpha software * Provides a set of usefull methods for determining what an object is at runtime, and raising an exception * Avoids creating these methods in Object directly, and instead extends the objects passed in (although it does add them directly to Numeric due to constraints in Ruby's Numeric implementation) * Allows for method chaining to provide a dose of syntactic sugar == SYNOPSIS: Imagine you have a method to calculate sunrise buried within a 1D planet simulator codebase. Throughout the codebase, validations are used to check data input, and there is a well thoughtout and well written test suite. def calc_sunrise(day, month) sunrise = (day - 50000)/month # arbitrary calculation that assumes day is a number and not negative end However, Joey your coworker hacks away and calls the following function: PlanetEarth.sunrise = calc_sunrise(-5, 1) Code executes, no exceptions are raised, but earths sunrise changes to a weird value. No amount of unit testing, specing, validating outside the model would have stopped Joey from making this hambone maneuver. Checking the arguments within the method would have prevented this: def calc_sunrise(day, month) raise ArgumentError.new("day must be numeric") unless day.kind_of?(Numeric) raise ArgumentError.new("day must be in range of 1-31") unless day > 1 && day < 31 raise ArgumentError.new("month must be numeric") unless month.kind_of?(Numeric) raise ArgumentError.new("month must be in range of 1-31") unless month > 1 && day < 31 # note subtle bug raise ArgumentError.new("month must not be nil") unless month > 1 && month < 31 ...sunrise calc... end But writing this sort of code is slow and error prone. Wouldn't you like to do this instead? require 'higher_expectations' class PlanetCalculations include HigherExpectations def calc_sunrise(day, month) has_expectations(day, month) # attach expectation methods to each object day.must_be_an(Integer) # day must kind_of? Integer or an exception will be raised day.must_be_in_range(1..31) # day must be in the given range or exception # a neat combination of both month.must_be_an(Integer).and_must_be_in_range(1..31) # since it raises an exception, its trappable, allowing for more flexible handling month.must_be_nil rescue ArgumentError nil ...sunrise calc end end ...without comments: def calc_sunrise(day,month) has_expectations(day,month) day.must_be_a(Integer).and_must_be_in_range(1..31) month.must_be_a(Integer).and_must_be_in_range(1..31 ...sunrise calc... end See spec below for details on methods possible. Copyright (c) 2008 Justin Tyler Wiley (justintylerwiley.com), under GPL V3 == SPEC: HigherExpectations - should not raise an exception when included HigherExpectations#has_expectations - should loop through given objects, extending each with instance_expectations.rb methods InstanceMethods InstanceMethods#raise_ae - should raise an ArgumentException with the given message InstanceMethods#must_be_/must_not_be_ - true, false, and nil - should raise exception if expected to be true false or nil, and they are not - should not raise exception if expected to be true false or nil, and they are InstanceMethods#must_be and must_not_be a particular value - should raise exception if item must be something and isnt - should not raise exception if item must be something and IS - (#not) should raise exception if item must not be something and IS - (#not) should not raise exception if item must not be something and is not InstanceMethods#must_be_a and must_not_be_a particular class of object - should raise exception if item must be a class and isnt - should not raise exception if item must be a class and IS - (#not) should raise exception if item must not be a class and is not - (#not) should not raise exception if item must not be a class and IS InstanceMethods#must_be_in_range and must_not_be_in_range of numbers - should raise exception if item must be in a range and isnt - should not raise exception if item must be in a range and is - (#not) should raise exception if item in a range - (#not) should not raise exception if item not in range - should raise HigherExpectation exception if handed something besides and array or a range InstanceMethods#must_match and must_not_match a given pattern - should raise exception if item does not match - should not raise exception if item matches - (#not) should not raise exception if item does not match - (#not) should raise exception if item matches InstanceMethods#must_respond_to and must_not_respond_to a given method - should raise exception if item does not respond - should not raise exception if item respond - (#not) should raise exception if item responds - (#not) should not raise exception if does respond == REQUIREMENTS: * hoe == INSTALL: * To build and install the gem from withing higher_expectations directory: rake local_deploy * To build and install the gem independantly rake package sudo gem install higher_expectations (where x is version) == LICENSE: Copyright (C) 2008 Justin Tyler Wiley This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>
About
Provides a clean, easy way to check method arguments at runtime.
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published