sure 1.1.4
- utility belt for automated testing in python (inspired by should.js )
from sure import version
version.should.be.equal('1.1.4')
user@machine:~$ [sudo] pip install sure
available only on cpython (no support for Jython, IronPython, PyPy, etc)
Mind-blowing easy and fluent assertions.
import sure
(4).should.be.equal(2 + 2)
(7.5).should.eql(3.5 + 4)
(2).should.equal(8 / 4)
(3).shouldnt.be.equal(5)
{'foo': 'bar'}.should.equal({'foo': 'bar'})
{'foo': 'bar'}.should.eql({'foo': 'bar'})
{'foo': 'bar'}.must.be.equal({'foo': 'bar'})
"Awesome ASSERTIONS".lower().split().should.equal(['awesome', 'assertions'])
"""
THIS IS MY loose string
""".should.look_like('this is my loose string')
"""this one is different""".should_not.look_like('this is my loose string')
[].should.be.empty;
{}.should.be.empty;
set().should.be.empty;
"".should.be.empty;
().should.be.empty
range(0).should.be.empty;
# negate with:
[1, 2, 3].shouldnt.be.empty;
"Lincoln de Sousa".shouldnt.be.empty;
"Lincoln de Sousa".should_not.be.empty;
(1).should.be.within(0, 2)
(5).should.be.within(10)
# negate with:
(1).shouldnt.be.within(5, 6)
"g".should.be.within("gabriel")
'name'.should.be.within({'name': 'Gabriel'})
'Lincoln'.should.be.within(['Lincoln', 'Gabriel'])
# negate with:
'Bug'.shouldnt.be.within(['Sure 1.0'])
'Bug'.should_not.be.within(['Sure 1.0'])
Assert whether an object is or not None
:
value = None
value.should.be.none
None.should.be.none
"".should_not.be.none
(not None).should_not.be.none
Assert truthfulness:
from sure import this
True.should.be.ok
'truthy string'.should.be.ok
{'truthy': 'dictionary'}.should.be.ok
And negate truthfulness:
from sure import this
False.shouldnt.be.ok
''.should_not.be.ok
{}.shouldnot.be.ok
class Basket(object):
fruits = ["apple", "banana"]
basket1 = Basket()
basket1.should.have.property("fruits")
If the programmer calls have.property()
it returns an assertion
builder of the property if it exists, so that you can chain up
assertions for the property value itself.
class Basket(object):
fruits = ["apple", "banana"]
basket2 = Basket()
basket2.should.have.property("fruits").being.equal(["apple", "banana"])
basket2.should.have.property("fruits").with_value.equal(["apple", "banana"])
basket2.should.have.property("fruits").with_value.being.equal(["apple", "banana"])
basket3 = dict(fruits=["apple", "banana"])
basket3.should.have.key("fruits")
If the programmer calls have.key()
it returns an assertion
builder of the key if it exists, so that you can chain up
assertions for the dictionary key value itself.
person = dict(name=None)
person.should.have.key("name").being.none
person.should.have.key("name").being.equal(None)
[3, 4].should.have.length_of(2)
"Python".should.have.length_of(6)
{'john': 'person'}.should_not.have.length_of(2)
Assert the magnitude of objects with {X}.should.be.greater_than(Y)
and {Y}.should.be.lower_than(X)
as well as {X}.should.be.greater_than_or_equal_to(Y)
and {Y}.should.be.lower_than_or_equal_to(X)
(5).should.be.greater_than(4)
(5).should_not.be.greater_than(10)
(1).should.be.lower_than(2)
(1).should_not.be.lower_than(0)
(5).should.be.greater_than_or_equal_to(4)
(5).should_not.be.greater_than_or_equal_to(10)
(1).should.be.lower_than_or_equal_to(2)
(1).should_not.be.lower_than_or_equal_to(0)
You can use this feature to assert that a callable raises an exception:
import sure
range.when.called_with(10, step="20").should.throw(TypeError, "range() takes no keyword arguments")
range.when.called_with("chuck norris").should.throw("range() integer end argument expected, got str.")
range.when.called_with("chuck norris").should.throw(TypeError)
range.when.called_with(10).should_not.throw(TypeError)
This is a shorthand for testing that a callable returns the expected result
import sure
range.when.called_with(2).should.return_value([0, 1])
this is the same as
value = range(2)
value.should.equal([0, 1])
there are no differences between those 2 possibilities, use at will
this takes a type name and checks if the class matches that name
import sure
{}.should.be.a('dict')
(5).should.be.an('int')
# also works with paths
range(10).should.be.a('collections.Iterable')
this takes the class (type) itself and checks if the object is an instance of it
import sure
u"".should.be.an(unicode)
[].should.be.a(list)
assert the instance value above and below num
import sure
(10).should.be.below(11)
(10).should.be.above(9)
(10).should_not.be.above(11)
(10).should_not.be.below(9)
Whether you don't like the object.should
syntax or you are simply
not running CPython, sure still allows you to use any of the
assertions above, all you need to do is wrap the object that is being
compared in one of the following options: it
, this
, those
and
these
.
from sure import it, this, those, these
(10).should.be.equal(5 + 5)
this(10).should.be.equal(5 + 5)
it(10).should.be.equal(5 + 5)
these(10).should.be.equal(5 + 5)
those(10).should.be.equal(5 + 5)
from sure import it, this, those, these, expect
assert (10).should.be.equal(5 + 5)
assert this(10).should.be.equal(5 + 5)
assert it(10).should.be.equal(5 + 5)
assert these(10).should.be.equal(5 + 5)
assert those(10).should.be.equal(5 + 5)
expect(10).to.be.equal(5 + 5)
expect(10).to.not_be.equal(8)
Test if something is or not callable
import sure
range.should.be.callable
(lambda: None).should.be.callable;
(123).should_not.be.callable
you can use or not the assert
keyword, sure internally already
raises an appropriate AssertionError
with an assertion message so
that you don't have to specify your own, but you can still use
assert
if you find it more semantic
Example:
import sure
"Name".lower().should.equal('name')
# or you can also use
assert "Name".lower().should.equal('name')
# or still
from sure import this
assert this("Name".lower()).should.equal('name')
# also without the `assert`
this("Name".lower()).should.equal('name')
Any of the examples above will raise their own AssertionError
with a
meaningful error message.
Sure provides you with a lot of synonyms so that you can pick the ones that makes more sense for your tests.
Note that the examples below are merely illustrative, they work not only with numbers but with any of the assertions you read early in this documentation.
(2 + 2).should.be.equal(4)
(2 + 2).must.be.equal(4)
(2 + 2).does.equals(4)
(2 + 2).do.equals(4)
from sure import expect
(2).should_not.be.equal(3)
(2).shouldnt.be.equal(3)
(2).doesnt.equals(3)
(2).does_not.equals(3)
(2).doesnot.equals(3)
(2).dont.equal(3)
(2).do_not.equal(3)
expect(3).to.not_be.equal(1)
Any of those synonyms work as an alias to the assertion builder:
be
being
to
when
have
with_value
from sure import expect
{"foo": 1}.must.with_value.being.equal({"foo": 1})
{"foo": 1}.does.have.key("foo").being.with_value.equal(1)
(2).should.equal(2)
(2).should.equals(2)
(2).should.eql(2)
(not None).should.be.ok
(not None).should.be.truthy
(not None).should.be.true
False.should.be.falsy
False.should.be.false
False.should_not.be.true
False.should_not.be.ok
None.should_not.be.true
None.should_not.be.ok
Sure! 👍
Just export the SURE_DISABLE_NEW_SYNTAX
environment variable before
running your tests.
export SURE_DISABLE_NEW_SYNTAX=True
Those are the python versions that support the assertions above CPython
Python ~= 2.6 (CPython)
Python ~= 2.7 (CPython)
Jython
PyPy
IronPython
UnladenSwallow
StacklessPython
...
Sure has a slick algorithm that makes use of the
ctypes, and although it is
also available in other implementations such as
Jython does have the ctypes
module, only
the CPython provides
ctypes.pythonapi
,
required by sure.
Differently of ruby python doesn't have
open classes,
but Lincoln de Sousa came out with a
super sick code that uses the ctypes module to create a pointer to the
__dict__
of builtin types.
Yes, it is dangerous, non-pythonic and should not be used in production code.
Although sure
is here to be used ONLY in test code, therefore it
should be running in ONLY possible environments: your local
machine or your continuous-integration server.
The assertion library is 100% inspired be the awesomeness of should.js which is simple, declarative and fluent.
Sure strives to provide everything a python developer needs in an assertion:
-
Assertion messages are easy to understand
-
When comparing iterables the comparation is recursive and shows exactly where is the error
-
Fluency: the builtin types are changed in order to provide awesome simple assertions
Sure still provides to all the assertions from v0.10 up, you can find the old documentation here
from sure import that
is not deprecated, usefrom sure.deprecated import that
instead, but aim on replacing usage ofthat()
toexpect()
Gabriel Falcão and Lincoln Clarete
Copyright (C) <2012> Gabriel Falcão <gabriel@nacaolivre.org>
Copyright (C) <2012> Lincoln Clarete <lincoln@comum.org>
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/>.