diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 41fde553fb1..fb975dcfc3d 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* Introduce assert_not to replace warty 'assert !foo'. *Jeremy Kemper*
+
* Prevent `Callbacks#set_callback` from setting the same callback twice.
before_save :foo, :bar, :foo
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 8466049e201..88aebba5c5b 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -3,6 +3,22 @@ require 'active_support/core_ext/object/blank'
module ActiveSupport
module Testing
module Assertions
+ # Assert that an expression is not truthy. Passes if object is
+ # +nil+ or +false+. "Truthy" means "considered true in a conditional"
+ # like if foo.
+ #
+ # assert_not nil # => true
+ # assert_not false # => true
+ # assert_not 'foo' # => 'foo' is not nil or false
+ #
+ # An error message can be specified.
+ #
+ # assert_not foo, 'foo should be false'
+ def assert_not(object, message = nil)
+ message ||= "Expected #{mu_pp(object)} to be nil or false"
+ assert !object, message
+ end
+
# Test numeric difference between the return value of an expression as a
# result of what is evaluated in the yielded block.
#
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index 7f732a1d20b..44fe6487104 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -15,6 +15,27 @@ class AssertDifferenceTest < ActiveSupport::TestCase
@object.num = 0
end
+ def test_assert_not
+ assert_not nil
+ assert_not false
+
+ begin
+ assert_not true
+ rescue Exception => e
+ assert_equal 'Expected true to be nil or false', e.message
+ else
+ fail 'assert_not true should fail'
+ end
+
+ begin
+ assert_not true, 'custom'
+ rescue Exception => e
+ assert_equal 'custom', e.message
+ else
+ fail 'assert_not true should fail'
+ end
+ end
+
def test_assert_no_difference
assert_no_difference '@object.num' do
# ...