Package: pysome
PySomePySomebrings theexpect(...).to_be(...)syntax to python to give developers more
flexible options for testing of nested objects.Installation$ pip install pysomeUsage:ExamplefrompysomeimportSome,SomeList,SomeDict,expect# some large nested api response you want to testapi_response={"menu":{"tags":[{"id":1,"z-index":12},{"id":2,"name":"ax7"},{"id":5,"name":"ax7","z-index":12},{"id":2,"alias":"iivz"},],"randomInt":4562,"auth_token":"1lm7QOvTDj","labels":{"en":{"name":"name","delete":"remove","add":"insert"},"de":{"name":"Name","delete":"löschen","add":"hinzufügen"}}}}# test only important stuffexpect(api_response).to_be({"menu":{"tags":SomeList(SomeDict(id=Some(int))),"randomInt":Some(int),"labels":Some(dict),}})Why useexpect(...).to_be(...)syntaxFor most of the basic stuff it would not be necessary to use theexpect(...).to_be(...)syntax.
You could for example safely do something like:frompysomeimportSomeassert{"a":12,"b":"x","c":{}}=={"a":Some(int),"b":Some(str),"c":Some(dict)}Out of different reasons it is still advised to useexpect(...).to_be(...)Some APISomeSomeequals all objects under the given conditions defined by its args. It
equals if any of the conditions is true. A condition can either betype,Callableor anotherSome.frompysomeimportSome,expectexpect(...).to_be(Some())# equals alwaysexpect(12).to_be(Some(int))# equals any intexpect("abc").to_be(Some(int,str))# equals all str and all intSomecan equal arbitrary objects by given functions:frompysomeimportSome,expectdefsums_to_10(x):returnsum(x)==10expect([2,3,5]).to_be(Some(sums_to_10))# 2 + 3 + 5 == 10expect([5,5]).to_be(Some(sums_to_10))# 5 + 5 = =10expect([1,2,3]).not_to_be(Some(sums_to_10))# 1 + 2 + 3 != 10expect({"a":12,"b":[4,3,3]}).to_be({"a":Some(int),# 12 is an int"b":Some(sums_to_10)# 4 + 3 + 3 == 10})but there are some useful pre-implemented subclasses ofSome:namealiasarguments*args = Union[type, Callable, Some]short descriptionSome()*argsequals all objects with any given type or functionAllOf()*argsequals only an object if all given arguments are fulfilledSomeOrNone()*argssame asSomebut also equals NoneSomeIterable()*args,length = None,is_type = Noneequals all Iterables under given conditionsSomeList()*args,length = None,is_type = Noneequals all Lists under given conditionsSomeDict()partial_dict: dict = None,**kwargsequals all dicts that have given subsetSomeIn()is_incontainerequals all objects that are in the given containerSomeWithLen()has_lenlength = None,min_length = None,max_length = Noneequals al objects that fulfill given length conditionsNotSome()is_not*argsequals all objects that do not fulfill any of the given conditionsSomeStr()regex=None,pattern=None,endswith=None,startswith=Noneequals all strings under given conditionsSomeEmail()is_emailequals strings that are email addressesSomeUuid()is_uuidequals strings that are UUIDsAllOfAllOf()equals all objects that fulfill all given conditions. So for example an objectAllOf(str, int)could only match an
object that inherits fromintandstrfrompysomeimportAllOf,expectdefless_than_10(x):returnx<10expect(8).to_be(AllOf(less_than_10,int))expect(8.5).not_to_be(AllOf(less_than_10,int))this is in contrast toSome()which equals all object tha fulfill only one of the conditionsSomeOrNoneSomeOrNone()is basically the same asSome()but it also equalsNone. This is very usefull if you want to test a key ofdictbut you do not care if it exists.frompysomeimportSomeOrNone,SomeDict,Some,expectexpect(12).to_be(SomeOrNone(int))expect(None).to_be(SomeOrNone(int))expect("abc").not_to_be(SomeOrNone(int))expect({"id":1,"name":"abc"}).to_be(SomeDict({"id":Some(int),"name":SomeOrNone(str)# name must be a string or non existent}))expect({"id":1,}).to_be(SomeDict({"id":Some(int),"name":SomeOrNone(str)}))SomeIterableSomeIterable()equals all objects that are iterable where every element of the iterable must fulfill the given conditions.frompysomeimportSomeIterable,expectexpect([1,2,3]).to_be(SomeIterable(int))expect([1,2.5,3]).not_to_be(SomeIterable(int))# you can also build nested structureexpect([[1,2,3],[4,5,6],[7,8,9]]).to_be(SomeIterable(SomeIterable(int)))SomeListSomeList()works exactly the same asSomeIterablewith the only difference that the Iterable must be of typelistSomeDictSomeDict()equals any dict that has all the given keys (as one dict or as kwargs). If you want to test if
a dict has exactly the keys use a default dict instead.frompysomeimportSomeDict,SomeList,Some,expectexpect([{"id":1,"name":"ab"},{"id":2,"z-index":-1},{"id":3},]).to_be(SomeList(SomeDict(id=Some(int))))SomeInSomeInequals all objects that are in its given container.frompysomeimportSomeIn,expectexpect("a").to_be(SomeIn({1,2,"a"}))expect("b").not_to_be(SomeIn({1,2,"a"}))SomeWithLenSomeWithLen()equals all objects that fulfill the given length condition. You can either give an explicit length or
define a range withmin_lengthandmax_lengthfrompysomeimportSomeWithLen,expectexpect([1,2,3]).to_be(SomeWithLen(3))expect([1,2,3]).to_be(SomeWithLen(min_length=1))expect([1,2,3]).not_to_be(SomeWithLen(max_length=2))NotSomeNotSomeis the opposite ofSome. It only equals an object if all given conditions are false.frompysomeimportNotSome,expectexpect(1).to_be(NotSome(str,float))expect(1.5).not_to_be(NotSome(str,float))SomeStrSomeStris a more flexible option to the simpleSome(str)that gives you more options like regex, simple wildcard patterns, endswith and startswith.frompysomeimportSomeStr,expectexpect("pysome").to_be(SomeStr())expect("pysome").to_be(SomeStr(pattern="p__ome"))expect("pysome").to_be(SomeStr(startswith="py"))expect("pysome").to_be(SomeStr(endswith="some"))expect("a8z").to_be(SomeStr(regex="a[0-9]z"))SomeEmailSomeEmailis a subclass ofSomeStrthat only equals a string if it is valid email addressfrompysomeimportSomeEmail,expectexpect("ab.cd@ef.gh").to_be(SomeEmail())expect("ab.cdef.gh").not_to_be(SomeEmail())SomeUuidSomeUuidis a subclass ofSomeStrthat only equals a string if it is valid UUIDfrompysomeimportSomeUuid,expectexpect("7de52743-8a1a-4782-9877-b10bf792172f").to_be(SomeUuid())expect("not a uuid").not_to_be(SomeUuid())Same API:warning:Sameshould only be used with theexpect(...).to_be(...)syntax!SameSame()objects can be used to check inside anexpectstatement that two values are the same.
Same also inherits fromSome()so you can also use default parameter. A singleSame()will therefore
behave exactly like aSome()frompysomeimportSame,expectexpect([1,1]).to_be([Same(),Same()])expect([1,2]).not_to_be([Same(),Same()])you can also provide names to the same to make multiple equal checksfrompysomeimportSame,expectexpect([1,"a",1,"a"]).to_be([Same(int,name="int_same"),Same(str,name="str_same"),Same(int,name="int_same"),Same(str,name="str_same")])namealiasshort descriptionSame()is_sameallSame()objects in one expect statement only equal if all do equalNotSame()is_uniqueallNotSame()objects in one expect statement only equal if all are uniqueNotSameNotSame()oris_uniquecan be used to check inside an expect statement that two values are unique (do not equal)frompysomeimportNotSame,expectexpect([1,2,3]).to_be([NotSame(),NotSame(),NotSame()])expect({"a":"abc","b":"abc"}).not_to_be({"a":NotSame(str),"b":NotSame(str)})Exceptions:namedescriptionPySomeExceptionParent class of all Exceptions that are raised bypysomeMustReturnBool(PySomeException)A function used as a validator in anSome()must always return abool. Either the object equals or not. This exception is thrown if a function doesnt return aboolvalueInvalidArgument(PySomeException)This exception is raised if a given argument to apysomeclass is invalidInvalidFunction(InvalidArgument)A function provided as condition to a Some must except exactly one parameter. If it doest this exception is thrownSameOutsideExpect()If you try to compare a Same object outside of anexpect(...).to_be(...)this error is raise