Fixtures to help testing functionality¶
Utilities which modify or replace code to help with doctesting functionality. Wrappers, proxies and mockups are typical examples of fixtures.
AUTHORS:
- Martin von Gagern (2014-12-15): AttributeAccessTracerProxy and trace_method 
- Martin von Gagern (2015-01-02): Factor out TracerHelper and reproducible_repr 
EXAMPLES:
You can use trace_method() to see how a method
communicates with its surroundings:
sage: class Foo():
....:     def f(self):
....:         self.y = self.g(self.x)
....:     def g(self, arg):
....:         return arg + 1
....:
sage: foo = Foo()
sage: foo.x = 3
sage: from sage.doctest.fixtures import trace_method
sage: trace_method(foo, "f")
sage: foo.f()
enter f()
  read x = 3
  call g(3) -> 4
  write y = 4
exit f -> None
>>> from sage.all import *
>>> class Foo():
...     def f(self):
...         self.y = self.g(self.x)
...     def g(self, arg):
...         return arg + Integer(1)
....:
>>> foo = Foo()
>>> foo.x = Integer(3)
>>> from sage.doctest.fixtures import trace_method
>>> trace_method(foo, "f")
>>> foo.f()
enter f()
  read x = 3
  call g(3) -> 4
  write y = 4
exit f -> None
- class sage.doctest.fixtures.AttributeAccessTracerHelper(delegate, prefix=' ', reads=True)[source]¶
- Bases: - object- Helper to print proxied access to attributes. - This class does the actual printing of access traces for objects proxied by - AttributeAccessTracerProxy. The fact that it’s not a proxy at the same time helps avoiding complicated attribute access syntax.- INPUT: - delegate– the actual object to be proxied
- prefix– (default:- " ") string to prepend to each printed output
- reads– (default:- True) whether to trace read access as well
 - EXAMPLES: - sage: class Foo(): ....: def f(self, *args): ....: return self.x*self.x ....: sage: foo = Foo() sage: from sage.doctest.fixtures import AttributeAccessTracerHelper sage: pat = AttributeAccessTracerHelper(foo) sage: pat.set("x", 2) write x = 2 sage: pat.get("x") read x = 2 2 sage: pat.get("f")(3) call f(3) -> 4 4 - >>> from sage.all import * >>> class Foo(): ... def f(self, *args): ... return self.x*self.x ....: >>> foo = Foo() >>> from sage.doctest.fixtures import AttributeAccessTracerHelper >>> pat = AttributeAccessTracerHelper(foo) >>> pat.set("x", Integer(2)) write x = 2 >>> pat.get("x") read x = 2 2 >>> pat.get("f")(Integer(3)) call f(3) -> 4 4 - get(name)[source]¶
- Read an attribute from the wrapped delegate object. - If that value is a method (i.e. a callable object which is not contained in the dictionary of the object itself but instead inherited from some class) then it is replaced by a wrapper function to report arguments and return value. Otherwise an attribute read access is reported. - EXAMPLES: - sage: class Foo(): ....: def f(self, *args): ....: return self.x*self.x ....: sage: foo = Foo() sage: foo.x = 2 sage: from sage.doctest.fixtures import AttributeAccessTracerHelper sage: pat = AttributeAccessTracerHelper(foo) sage: pat.get("x") read x = 2 2 sage: pat.get("f")(3) call f(3) -> 4 4 - >>> from sage.all import * >>> class Foo(): ... def f(self, *args): ... return self.x*self.x ....: >>> foo = Foo() >>> foo.x = Integer(2) >>> from sage.doctest.fixtures import AttributeAccessTracerHelper >>> pat = AttributeAccessTracerHelper(foo) >>> pat.get("x") read x = 2 2 >>> pat.get("f")(Integer(3)) call f(3) -> 4 4 
 - set(name, val)[source]¶
- Write an attribute to the wrapped delegate object. - The name and new value are also reported in the output. - EXAMPLES: - sage: class Foo(): ....: pass ....: sage: foo = Foo() sage: from sage.doctest.fixtures import AttributeAccessTracerHelper sage: pat = AttributeAccessTracerHelper(foo) sage: pat.set("x", 2) write x = 2 sage: foo.x 2 - >>> from sage.all import * >>> class Foo(): ... pass ....: >>> foo = Foo() >>> from sage.doctest.fixtures import AttributeAccessTracerHelper >>> pat = AttributeAccessTracerHelper(foo) >>> pat.set("x", Integer(2)) write x = 2 >>> foo.x 2 
 
- class sage.doctest.fixtures.AttributeAccessTracerProxy(delegate, **kwds)[source]¶
- Bases: - object- Proxy object which prints all attribute and method access to an object. - The implementation is kept lean since all access to attributes of the proxy itself requires complicated syntax. For this reason, the actual handling of attribute access is delegated to a - AttributeAccessTracerHelper.- INPUT: - delegate– the actual object to be proxied
- prefix– (default:- " ") string to prepend to each printed output
- reads– (default:- True) whether to trace read access as well
 - EXAMPLES: - sage: class Foo(): ....: def f(self, *args): ....: return self.x*self.x ....: sage: foo = Foo() sage: from sage.doctest.fixtures import AttributeAccessTracerProxy sage: pat = AttributeAccessTracerProxy(foo) sage: pat.x = 2 write x = 2 sage: pat.x read x = 2 2 sage: pat.f(3) call f(3) -> 4 4 - >>> from sage.all import * >>> class Foo(): ... def f(self, *args): ... return self.x*self.x ....: >>> foo = Foo() >>> from sage.doctest.fixtures import AttributeAccessTracerProxy >>> pat = AttributeAccessTracerProxy(foo) >>> pat.x = Integer(2) write x = 2 >>> pat.x read x = 2 2 >>> pat.f(Integer(3)) call f(3) -> 4 4 - __getattribute__(name)[source]¶
- Read an attribute from the wrapped delegate object. - If that value is a method (i.e. a callable object which is not contained in the dictionary of the object itself but instead inherited from some class) then it is replaced by a wrapper function to report arguments and return value. Otherwise an attribute read access is reported. - EXAMPLES: - sage: class Foo(): ....: def f(self, *args): ....: return self.x*self.x ....: sage: foo = Foo() sage: foo.x = 2 sage: from sage.doctest.fixtures import AttributeAccessTracerProxy sage: pat = AttributeAccessTracerProxy(foo) sage: pat.x read x = 2 2 sage: pat.f(3) call f(3) -> 4 4 - >>> from sage.all import * >>> class Foo(): ... def f(self, *args): ... return self.x*self.x ....: >>> foo = Foo() >>> foo.x = Integer(2) >>> from sage.doctest.fixtures import AttributeAccessTracerProxy >>> pat = AttributeAccessTracerProxy(foo) >>> pat.x read x = 2 2 >>> pat.f(Integer(3)) call f(3) -> 4 4 
 - __setattr__(name, val)[source]¶
- Write an attribute to the wrapped delegate object. - The name and new value are also reported in the output. - EXAMPLES: - sage: class Foo(): ....: pass ....: sage: foo = Foo() sage: from sage.doctest.fixtures import AttributeAccessTracerProxy sage: pat = AttributeAccessTracerProxy(foo) sage: pat.x = 2 write x = 2 sage: foo.x 2 - >>> from sage.all import * >>> class Foo(): ... pass ....: >>> foo = Foo() >>> from sage.doctest.fixtures import AttributeAccessTracerProxy >>> pat = AttributeAccessTracerProxy(foo) >>> pat.x = Integer(2) write x = 2 >>> foo.x 2 
 
- sage.doctest.fixtures.reproducible_repr(val)[source]¶
- String representation of an object in a reproducible way. - Note - This function is deprecated, in most cases it suffices to use the automatic sorting of dictionary keys and set items by a displayhook. See - sage.doctest.forker.init_sage(). If used in a format string, use- IPython.lib.pretty.pretty(). In the rare cases where the ordering of the elements is not reliable or transitive,- sortedwith a sane key can be used instead.- This tries to ensure that the returned string does not depend on factors outside the control of the doctest. One example is the order of elements in a hash-based structure. For most objects, this is simply the - reprof the object.- All types for which special handling had been implemented are covered by the examples below. If a doctest requires special handling for additional types, this function may be extended appropriately. It is an error if an argument to this function has a non-reproducible - reprimplementation and is not explicitly mentioned in an example case below.- INPUT: - val– an object to be represented
 - OUTPUT: - A string representation of that object, similar to what - reprreturns but for certain cases with more guarantees to ensure exactly the same result for semantically equivalent objects.- EXAMPLES: - sage: # not tested (test fails because of deprecation warning) sage: from sage.doctest.fixtures import reproducible_repr sage: print(reproducible_repr(set(["a", "c", "b", "d"]))) set(['a', 'b', 'c', 'd']) sage: print(reproducible_repr(frozenset(["a", "c", "b", "d"]))) frozenset(['a', 'b', 'c', 'd']) sage: print(reproducible_repr([1, frozenset("cab"), set("bar"), 0])) [1, frozenset(['a', 'b', 'c']), set(['a', 'b', 'r']), 0] sage: print(reproducible_repr({3.0: "three", "2": "two", 1: "one"})) # needs sage.rings.real_mpfr {'2': 'two', 1: 'one', 3.00000000000000: 'three'} sage: print(reproducible_repr("foo\nbar")) # demonstrate default case 'foo\nbar' - >>> from sage.all import * >>> # not tested (test fails because of deprecation warning) >>> from sage.doctest.fixtures import reproducible_repr >>> print(reproducible_repr(set(["a", "c", "b", "d"]))) set(['a', 'b', 'c', 'd']) >>> print(reproducible_repr(frozenset(["a", "c", "b", "d"]))) frozenset(['a', 'b', 'c', 'd']) >>> print(reproducible_repr([Integer(1), frozenset("cab"), set("bar"), Integer(0)])) [1, frozenset(['a', 'b', 'c']), set(['a', 'b', 'r']), 0] >>> print(reproducible_repr({RealNumber('3.0'): "three", "2": "two", Integer(1): "one"})) # needs sage.rings.real_mpfr {'2': 'two', 1: 'one', 3.00000000000000: 'three'} >>> print(reproducible_repr("foo\nbar")) # demonstrate default case 'foo\nbar' 
- sage.doctest.fixtures.trace_method(obj, meth, **kwds)[source]¶
- Trace the doings of a given method. It prints method entry with arguments, access to members and other methods during method execution as well as method exit with return value. - INPUT: - obj– the object containing the method
- meth– the name of the method to be traced
- prefix– (default:- " ") string to prepend to each printed output
- reads– (default:- True) whether to trace read access as well
 - EXAMPLES: - sage: class Foo(): ....: def f(self, arg=None): ....: self.y = self.g(self.x) ....: if arg: return arg*arg ....: def g(self, arg): ....: return arg + 1 ....: sage: foo = Foo() sage: foo.x = 3 sage: from sage.doctest.fixtures import trace_method sage: trace_method(foo, "f") sage: foo.f() enter f() read x = 3 call g(3) -> 4 write y = 4 exit f -> None sage: foo.f(3) enter f(3) read x = 3 call g(3) -> 4 write y = 4 exit f -> 9 9 - >>> from sage.all import * >>> class Foo(): ... def f(self, arg=None): ... self.y = self.g(self.x) ... if arg: return arg*arg ... def g(self, arg): ... return arg + Integer(1) ....: >>> foo = Foo() >>> foo.x = Integer(3) >>> from sage.doctest.fixtures import trace_method >>> trace_method(foo, "f") >>> foo.f() enter f() read x = 3 call g(3) -> 4 write y = 4 exit f -> None >>> foo.f(Integer(3)) enter f(3) read x = 3 call g(3) -> 4 write y = 4 exit f -> 9 9