<strong>Sage</strong> Developer’s <strong>Guide</strong>, Release 6.1.1Writing Testable ExamplesThe code in the examples should pass automatic testing. This means that if the above code is in the file f.py (orf.sage), then sage -t f.py should not give any error messages. Testing occurs with full <strong>Sage</strong> preparsing ofinput within the standard <strong>Sage</strong> shell environment, as described in <strong>Sage</strong> Preparsing. Important: The file f.py is notimported when running tests unless you have arranged that it be imported into your <strong>Sage</strong> environment, i.e. unless itsfunctions are available when you start <strong>Sage</strong> using the sage command. For example, the function AA() in the fileSAGE_ROOT/src/sage/algebras/steenrod/steenrod_algebra.py includes an EXAMPLES blockcontaining the following:sage: from sage.algebras.steenrod.steenrod_algebra import AA as Asage: A()mod 2 Steenrod algebra, milnor basis<strong>Sage</strong> does not know about the function AA() by default, so it needs to be imported before it is tested. Hence the firstline in the example.When writing documentation, keep the following points in mind:• All input is preparsed before being passed to Python, e.g. 2/3 is replaced by Integer(2)/Integer(3),which evaluates to 2/3 as a rational instead of the Python int 0. For more information on preparsing, see <strong>Sage</strong>Preparsing.• If a test outputs to a file, the file should be a temporary file.temporary filename, or tmp_dir() to get a temporary directory.SAGE_ROOT/src/sage/plot/graphics.py):Use tmp_filename() to get aFor example (taken from the filesage: plot(x^2 - 5, (x, 0, 5), ymin=0).save(tmp_filename(ext=’.png’))• You may write tests that span multiple lines. The best way to do so is to use the line continuation marker ....:sage: for n in srange(1,10):....: if n.is_prime():....: print n,2 3 5 7If you have a long line of code, you may want to consider adding a backslash to the end of the line, which tellsthe doctesting framework to join that current line with the next. This syntax is non-standard so may be removedin a future version of <strong>Sage</strong>, but in the mean time it can be useful for breaking up large integers across multiplelines:sage: n = 123456789123456789123456789\....: 123456789123456789123456789sage: n.is_prime()FalseSpecial Markup to Influence TestsThere are a number of magic comments that you can put into the example code that change how the output is verifiedby the <strong>Sage</strong> doctest framework. Here is a comprehensive list:• If a test line contains the comment random, it is executed but it is not checked that the output agreeswith the output in the documentation string. For example, the docstring for the __hash__ method forCombinatorialObject in SAGE_ROOT/src/sage/combinat/combinat.py includes the lines:sage: c = CombinatorialObject([1,2,3])sage: hash(c) # random133541667597179319528 Chapter 4. Writing Code for <strong>Sage</strong>
<strong>Sage</strong> Developer’s <strong>Guide</strong>, Release 6.1.1sage: c.__hash__()1335416675971793195# randomHowever, most functions generating pseudorandom output do not need this tag since the doctesting frameworkguarantees the state of the pseudorandom number generators (PRNGs) used in <strong>Sage</strong> for a given doctest.See Randomized Testing for details on this framework. It is preferable to write tests that do not expose thisnon-determinism, for example rather than checking the value of the hash in a dockets, one could illustratesuccessfully using it as a key in a dict.• If a line contains the comment long time then that line is not tested unless the --long option is given, e.g.sage -t --long f.py. Use this to include examples that take more than about a second to run. Thesewill not be run regularly during <strong>Sage</strong> development, but will get run before major releases. No example shouldtake more than about 30 seconds.For instance, here is part of the docstring from the regulator method for rational elliptic curves, from thefile SAGE_ROOT/devel/sage/sage/schemes/elliptic_curves/ell_rational.py:sage: E = EllipticCurve([0, 0, 1, -1, 0])sage: E.regulator() # long time (1 second)0.0511114082399688• If a comment contains tol or tolerance, numerical results are only verified to the given tolerance. Thismay be prefixed by abs[olute] or rel[ative] to specify whether to measure absolute or relative error;this defaults to relative error except when the expected value is exactly zero:sage: RDF(pi) # abs tol 1e-53.14159sage: [10^n for n in [0.0 .. 4]] # rel tol 2e-4[0.9999, 10.001, 100.01, 999.9, 10001]This can be useful when the exact output is subject to rounding error and/or processor floating point arithmeticvariation. Here are some more examples.A singular value decomposition of a matrix will produce two unitary matrices. Over the reals, this means theinverse of the matrix is equal to its transpose. We test this result by applying the norm to a matrix difference.The result will usually be a “small” number, distinct from zero:sage: A = matrix(RDF, 8, range(64))sage: U, S, V = A.SVD()sage: (U.transpose()*U-identity_matrix(8)).norm(p=2) # abs tol 1e-100.0The 8-th cyclotomic field is generated by the complex number e iπ 4 . Here we compute a numerical approximation:sage: K. = CyclotomicField(8)sage: N(zeta8) # absolute tolerance 1e-100.7071067812 + 0.7071067812*IA relative tolerance on a root of a polynomial. Notice that the root should normally print as 1e+16, or somethingsimilar. However, the tolerance testing causes the doctest framework to use the output in a computation, so othervalid text representations of the predicted value may be used. However, they must fit the pattern defined by theregular expression float_regex in sage.doctest.parsing:sage: y = polygen(RDF, ’y’)sage: p = (y - 10^16)*(y-10^(-13))*(y-2); py^3 - 1e+16*y^2 + 2e+16*y - 2000.0sage: p.roots(multiplicities=False)[2] # relative tol 1e-10100000000000000004.1. General Conventions 29
- Page 1: Sage Developer’s GuideRelease 6.1
- Page 4 and 5: 7 Indices and tables 129Bibliograph
- Page 6 and 7: Sage Developer’s Guide, Release 6
- Page 8 and 9: Sage Developer’s Guide, Release 6
- Page 10 and 11: Sage Developer’s Guide, Release 6
- Page 12 and 13: Sage Developer’s Guide, Release 6
- Page 14 and 15: Sage Developer’s Guide, Release 6
- Page 16 and 17: Sage Developer’s Guide, Release 6
- Page 18 and 19: Sage Developer’s Guide, Release 6
- Page 20 and 21: Sage Developer’s Guide, Release 6
- Page 22 and 23: Sage Developer’s Guide, Release 6
- Page 24 and 25: Sage Developer’s Guide, Release 6
- Page 26 and 27: Sage Developer’s Guide, Release 6
- Page 28 and 29: Sage Developer’s Guide, Release 6
- Page 30 and 31: Sage Developer’s Guide, Release 6
- Page 34 and 35: Sage Developer’s Guide, Release 6
- Page 36 and 37: Sage Developer’s Guide, Release 6
- Page 38 and 39: Sage Developer’s Guide, Release 6
- Page 40 and 41: Sage Developer’s Guide, Release 6
- Page 42 and 43: Sage Developer’s Guide, Release 6
- Page 44 and 45: Sage Developer’s Guide, Release 6
- Page 46 and 47: Sage Developer’s Guide, Release 6
- Page 48 and 49: Sage Developer’s Guide, Release 6
- Page 50 and 51: Sage Developer’s Guide, Release 6
- Page 52 and 53: Sage Developer’s Guide, Release 6
- Page 54 and 55: Sage Developer’s Guide, Release 6
- Page 56 and 57: Sage Developer’s Guide, Release 6
- Page 58 and 59: Sage Developer’s Guide, Release 6
- Page 60 and 61: Sage Developer’s Guide, Release 6
- Page 62 and 63: Sage Developer’s Guide, Release 6
- Page 64 and 65: Sage Developer’s Guide, Release 6
- Page 66 and 67: Sage Developer’s Guide, Release 6
- Page 68 and 69: Sage Developer’s Guide, Release 6
- Page 70 and 71: Sage Developer’s Guide, Release 6
- Page 72 and 73: Sage Developer’s Guide, Release 6
- Page 74 and 75: Sage Developer’s Guide, Release 6
- Page 76 and 77: Sage Developer’s Guide, Release 6
- Page 78 and 79: Sage Developer’s Guide, Release 6
- Page 80 and 81: Sage Developer’s Guide, Release 6
- Page 82 and 83:
Sage Developer’s Guide, Release 6
- Page 84 and 85:
Sage Developer’s Guide, Release 6
- Page 86 and 87:
Sage Developer’s Guide, Release 6
- Page 88 and 89:
Sage Developer’s Guide, Release 6
- Page 90 and 91:
Sage Developer’s Guide, Release 6
- Page 92 and 93:
Sage Developer’s Guide, Release 6
- Page 94 and 95:
Sage Developer’s Guide, Release 6
- Page 96 and 97:
Sage Developer’s Guide, Release 6
- Page 98 and 99:
Sage Developer’s Guide, Release 6
- Page 100 and 101:
Sage Developer’s Guide, Release 6
- Page 102 and 103:
Sage Developer’s Guide, Release 6
- Page 104 and 105:
Sage Developer’s Guide, Release 6
- Page 106 and 107:
Sage Developer’s Guide, Release 6
- Page 108 and 109:
Sage Developer’s Guide, Release 6
- Page 110 and 111:
Sage Developer’s Guide, Release 6
- Page 112 and 113:
Sage Developer’s Guide, Release 6
- Page 114 and 115:
Sage Developer’s Guide, Release 6
- Page 116 and 117:
Sage Developer’s Guide, Release 6
- Page 118 and 119:
Sage Developer’s Guide, Release 6
- Page 120 and 121:
Sage Developer’s Guide, Release 6
- Page 122 and 123:
Sage Developer’s Guide, Release 6
- Page 124 and 125:
Sage Developer’s Guide, Release 6
- Page 126 and 127:
Sage Developer’s Guide, Release 6
- Page 128 and 129:
Sage Developer’s Guide, Release 6
- Page 130 and 131:
Sage Developer’s Guide, Release 6
- Page 132 and 133:
Sage Developer’s Guide, Release 6
- Page 134 and 135:
Sage Developer’s Guide, Release 6
- Page 136 and 137:
Sage Developer’s Guide, Release 6