-
# HG changeset patch
# User Nicolas M. Thiery <nthiery@users.sf.net>
# Date 1263761923 -3600
# Node ID e605190b01c65e5fac335cd4239e6f8834bbdf30
# Parent c844f8d6197b2089c42e8e3763967fbce58a3a22
#7921: Patch 2: stronger category tests
- More category tests (_test_category, _test_elements)
- Improvements to TestSuite
- Partial support for nested test suites
- Support for basic TestSuite(x) for x any Python object
- Added TestSuite call for Spec and ref to #7946
- Corresponding doctest updates
diff --git a/sage/algebras/steenrod_algebra.py b/sage/algebras/steenrod_algebra.py
a
|
b
|
class SteenrodAlgebra_generic(Algebra): |
119 | 119 | sage: A = SteenrodAlgebra(3) |
120 | 120 | sage: A.category() |
121 | 121 | Category of algebras over Finite Field of size 3 |
122 | | sage: TestSuite(A).run() |
| 122 | sage: TestSuite(A).run() # todo: fix category inheritance for elements of A |
| 123 | Failure in _test_category: |
| 124 | ... |
| 125 | ------------------------------------------------------------ |
| 126 | The following tests failed: _test_category |
| 127 | Failure in _test_elements |
| 128 | The following tests failed: _test_elements |
123 | 129 | """ |
124 | 130 | from sage.rings.arith import is_prime |
125 | 131 | if not is_prime(p): |
-
diff --git a/sage/categories/algebras_with_basis.py b/sage/categories/algebras_with_basis.py
a
|
b
|
class AlgebrasWithBasis(Category_over_ba |
60 | 60 | running ._test_additive_associativity() . . . pass |
61 | 61 | running ._test_an_element() . . . pass |
62 | 62 | running ._test_associativity() . . . pass |
63 | | running ._test_element_pickling() . . . pass |
| 63 | running ._test_category() . . . pass |
| 64 | running ._test_elements() . . . |
| 65 | Running the test suite of self.an_element() |
| 66 | running ._test_category() . . . pass |
| 67 | running ._test_not_implemented_methods() . . . pass |
| 68 | running ._test_pickling() . . . pass |
| 69 | pass |
64 | 70 | running ._test_not_implemented_methods() . . . pass |
65 | 71 | running ._test_one() . . . pass |
66 | 72 | running ._test_pickling() . . . pass |
-
diff --git a/sage/categories/coxeter_groups.py b/sage/categories/coxeter_groups.py
a
|
b
|
class CoxeterGroups(Category): |
68 | 68 | sage: W = CoxeterGroups().example(); TestSuite(W).run(verbose = "True") |
69 | 69 | running ._test_an_element() . . . pass |
70 | 70 | running ._test_associativity() . . . pass |
71 | | running ._test_element_pickling() . . . pass |
| 71 | running ._test_category() . . . pass |
| 72 | running ._test_elements() . . . |
| 73 | Running the test suite of self.an_element() |
| 74 | running ._test_category() . . . pass |
| 75 | running ._test_not_implemented_methods() . . . pass |
| 76 | running ._test_pickling() . . . pass |
| 77 | pass |
72 | 78 | running ._test_enumerated_set_contains() . . . pass |
73 | 79 | running ._test_enumerated_set_iter_cardinality() . . . pass |
74 | 80 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/commutative_additive_monoids.py b/sage/categories/examples/commutative_additive_monoids.py
a
|
b
|
class FreeCommutativeAdditiveMonoid(Free |
45 | 45 | sage: TestSuite(S).run(verbose = True) |
46 | 46 | running ._test_additive_associativity() . . . pass |
47 | 47 | running ._test_an_element() . . . pass |
48 | | running ._test_element_pickling() . . . pass |
| 48 | running ._test_category() . . . pass |
| 49 | running ._test_elements() . . . |
| 50 | Running the test suite of self.an_element() |
| 51 | running ._test_category() . . . pass |
| 52 | running ._test_not_implemented_methods() . . . pass |
| 53 | running ._test_pickling() . . . pass |
| 54 | pass |
49 | 55 | running ._test_not_implemented_methods() . . . pass |
50 | 56 | running ._test_pickling() . . . pass |
51 | 57 | running ._test_some_elements() . . . pass |
-
diff --git a/sage/categories/examples/commutative_additive_semigroups.py b/sage/categories/examples/commutative_additive_semigroups.py
a
|
b
|
class FreeCommutativeAdditiveSemigroup(U |
43 | 43 | sage: TestSuite(S).run(verbose = True) |
44 | 44 | running ._test_additive_associativity() . . . pass |
45 | 45 | running ._test_an_element() . . . pass |
46 | | running ._test_element_pickling() . . . pass |
| 46 | running ._test_category() . . . pass |
| 47 | running ._test_elements() . . . |
| 48 | Running the test suite of self.an_element() |
| 49 | running ._test_category() . . . pass |
| 50 | running ._test_not_implemented_methods() . . . pass |
| 51 | running ._test_pickling() . . . pass |
| 52 | pass |
47 | 53 | running ._test_not_implemented_methods() . . . pass |
48 | 54 | running ._test_pickling() . . . pass |
49 | 55 | running ._test_some_elements() . . . pass |
-
diff --git a/sage/categories/examples/finite_coxeter_groups.py b/sage/categories/examples/finite_coxeter_groups.py
a
|
b
|
class DihedralGroup(UniqueRepresentation |
69 | 69 | sage: TestSuite(G).run(verbose = True) |
70 | 70 | running ._test_an_element() . . . pass |
71 | 71 | running ._test_associativity() . . . pass |
72 | | running ._test_element_pickling() . . . pass |
| 72 | running ._test_category() . . . pass |
| 73 | running ._test_elements() . . . |
| 74 | Running the test suite of self.an_element() |
| 75 | running ._test_category() . . . pass |
| 76 | running ._test_not_implemented_methods() . . . pass |
| 77 | running ._test_pickling() . . . pass |
| 78 | pass |
73 | 79 | running ._test_enumerated_set_contains() . . . pass |
74 | 80 | running ._test_enumerated_set_iter_cardinality() . . . pass |
75 | 81 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/finite_enumerated_sets.py b/sage/categories/examples/finite_enumerated_sets.py
a
|
b
|
class Example(UniqueRepresentation, Pare |
34 | 34 | |
35 | 35 | sage: TestSuite(C).run(verbose = True) |
36 | 36 | running ._test_an_element() . . . pass |
37 | | running ._test_element_pickling() . . . pass |
| 37 | running ._test_category() . . . pass |
| 38 | running ._test_elements() . . . |
| 39 | Running the test suite of self.an_element() |
| 40 | running ._test_pickling() . . . pass |
| 41 | pass |
38 | 42 | running ._test_enumerated_set_contains() . . . pass |
39 | 43 | running ._test_enumerated_set_iter_cardinality() . . . pass |
40 | 44 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/finite_monoids.py b/sage/categories/examples/finite_monoids.py
a
|
b
|
class IntegerModMonoid(UniqueRepresentat |
37 | 37 | sage: TestSuite(S).run(verbose = True) |
38 | 38 | running ._test_an_element() . . . pass |
39 | 39 | running ._test_associativity() . . . pass |
40 | | running ._test_element_pickling() . . . pass |
| 40 | running ._test_category() . . . pass |
| 41 | running ._test_elements() . . . |
| 42 | Running the test suite of self.an_element() |
| 43 | running ._test_category() . . . pass |
| 44 | running ._test_not_implemented_methods() . . . pass |
| 45 | running ._test_pickling() . . . pass |
| 46 | pass |
41 | 47 | running ._test_enumerated_set_contains() . . . pass |
42 | 48 | running ._test_enumerated_set_iter_cardinality() . . . pass |
43 | 49 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/finite_semigroups.py b/sage/categories/examples/finite_semigroups.py
a
|
b
|
class LeftRegularBand(UniqueRepresentati |
80 | 80 | sage: TestSuite(S).run(verbose = True) |
81 | 81 | running ._test_an_element() . . . pass |
82 | 82 | running ._test_associativity() . . . pass |
83 | | running ._test_element_pickling() . . . pass |
| 83 | running ._test_category() . . . pass |
| 84 | running ._test_elements() . . . |
| 85 | Running the test suite of self.an_element() |
| 86 | running ._test_category() . . . pass |
| 87 | running ._test_not_implemented_methods() . . . pass |
| 88 | running ._test_pickling() . . . pass |
| 89 | pass |
84 | 90 | running ._test_enumerated_set_contains() . . . pass |
85 | 91 | running ._test_enumerated_set_iter_cardinality() . . . pass |
86 | 92 | running ._test_enumerated_set_iter_list() . . . pass |
87 | 93 | running ._test_not_implemented_methods() . . . pass |
88 | 94 | running ._test_pickling() . . . pass |
89 | 95 | running ._test_some_elements() . . . pass |
90 | | |
91 | 96 | """ |
92 | 97 | |
93 | 98 | def __init__(self, alphabet=('a','b','c','d')): |
-
diff --git a/sage/categories/examples/finite_weyl_groups.py b/sage/categories/examples/finite_weyl_groups.py
a
|
b
|
class SymmetricGroup(UniqueRepresentatio |
50 | 50 | sage: TestSuite(S).run(verbose = True) |
51 | 51 | running ._test_an_element() . . . pass |
52 | 52 | running ._test_associativity() . . . pass |
53 | | running ._test_element_pickling() . . . pass |
| 53 | running ._test_category() . . . pass |
| 54 | running ._test_elements() . . . |
| 55 | Running the test suite of self.an_element() |
| 56 | running ._test_category() . . . pass |
| 57 | running ._test_not_implemented_methods() . . . pass |
| 58 | running ._test_pickling() . . . pass |
| 59 | pass |
54 | 60 | running ._test_enumerated_set_contains() . . . pass |
55 | 61 | running ._test_enumerated_set_iter_cardinality() . . . pass |
56 | 62 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/infinite_enumerated_sets.py b/sage/categories/examples/infinite_enumerated_sets.py
a
|
b
|
class NonNegativeIntegers(UniqueRepresen |
51 | 51 | |
52 | 52 | sage: TestSuite(NN).run(verbose = True) |
53 | 53 | running ._test_an_element() . . . pass |
54 | | running ._test_element_pickling() . . . pass |
| 54 | running ._test_category() . . . pass |
| 55 | running ._test_elements() . . . |
| 56 | Running the test suite of self.an_element() |
| 57 | running ._test_category() . . . pass |
| 58 | running ._test_not_implemented_methods() . . . pass |
| 59 | running ._test_pickling() . . . pass |
| 60 | pass |
55 | 61 | running ._test_enumerated_set_contains() . . . pass |
56 | 62 | running ._test_enumerated_set_iter_cardinality() . . . pass |
57 | 63 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/examples/monoids.py b/sage/categories/examples/monoids.py
a
|
b
|
class FreeMonoid(FreeSemigroup): |
46 | 46 | sage: TestSuite(S).run(verbose = True) |
47 | 47 | running ._test_an_element() . . . pass |
48 | 48 | running ._test_associativity() . . . pass |
49 | | running ._test_element_pickling() . . . pass |
| 49 | running ._test_category() . . . pass |
| 50 | running ._test_elements() . . . |
| 51 | Running the test suite of self.an_element() |
| 52 | running ._test_category() . . . pass |
| 53 | running ._test_not_implemented_methods() . . . pass |
| 54 | running ._test_pickling() . . . pass |
| 55 | pass |
50 | 56 | running ._test_not_implemented_methods() . . . pass |
51 | 57 | running ._test_one() . . . pass |
52 | 58 | running ._test_pickling() . . . pass |
-
diff --git a/sage/categories/examples/semigroups.py b/sage/categories/examples/semigroups.py
a
|
b
|
class LeftZeroSemigroup(UniqueRepresenta |
46 | 46 | sage: TestSuite(S).run(verbose = True) |
47 | 47 | running ._test_an_element() . . . pass |
48 | 48 | running ._test_associativity() . . . pass |
49 | | running ._test_element_pickling() . . . pass |
| 49 | running ._test_category() . . . pass |
| 50 | running ._test_elements() . . . |
| 51 | Running the test suite of self.an_element() |
| 52 | running ._test_category() . . . pass |
| 53 | running ._test_not_implemented_methods() . . . pass |
| 54 | running ._test_pickling() . . . pass |
| 55 | pass |
50 | 56 | running ._test_not_implemented_methods() . . . pass |
51 | 57 | running ._test_pickling() . . . pass |
52 | 58 | running ._test_some_elements() . . . pass |
… |
… |
class FreeSemigroup(UniqueRepresentation |
165 | 171 | sage: TestSuite(S).run(verbose = True) |
166 | 172 | running ._test_an_element() . . . pass |
167 | 173 | running ._test_associativity() . . . pass |
168 | | running ._test_element_pickling() . . . pass |
| 174 | running ._test_category() . . . pass |
| 175 | running ._test_elements() . . . |
| 176 | Running the test suite of self.an_element() |
| 177 | running ._test_category() . . . pass |
| 178 | running ._test_not_implemented_methods() . . . pass |
| 179 | running ._test_pickling() . . . pass |
| 180 | pass |
169 | 181 | running ._test_not_implemented_methods() . . . pass |
170 | 182 | running ._test_pickling() . . . pass |
171 | 183 | running ._test_some_elements() . . . pass |
… |
… |
class SubQuotientOfLeftZeroSemigroup(Uni |
326 | 338 | sage: TestSuite(S).run(verbose = True) |
327 | 339 | running ._test_an_element() . . . pass |
328 | 340 | running ._test_associativity() . . . pass |
329 | | running ._test_element_pickling() . . . pass |
| 341 | running ._test_category() . . . pass |
| 342 | running ._test_elements() . . . |
| 343 | Running the test suite of self.an_element() |
| 344 | running ._test_category() . . . pass |
| 345 | running ._test_not_implemented_methods() . . . pass |
| 346 | running ._test_pickling() . . . pass |
| 347 | pass |
330 | 348 | running ._test_not_implemented_methods() . . . pass |
331 | 349 | running ._test_pickling() . . . pass |
332 | 350 | running ._test_some_elements() . . . pass |
… |
… |
class IncompleteSubQuotientSemigroup(Uni |
528 | 546 | ... |
529 | 547 | AssertionError: Not implemented method: lift |
530 | 548 | |
531 | | sage: TestSuite(S).run(verbose = True) # todo: improve the error messages |
| 549 | sage: TestSuite(S).run(verbose = True) |
532 | 550 | running ._test_an_element() . . . pass |
533 | 551 | running ._test_associativity() . . . fail |
534 | 552 | Traceback (most recent call last): |
535 | 553 | ... |
536 | 554 | NotImplementedError: <abstract method retract at ...> |
537 | 555 | ------------------------------------------------------------ |
538 | | running ._test_element_pickling() . . . pass |
| 556 | running ._test_category() . . . pass |
| 557 | running ._test_elements() . . . |
| 558 | Running the test suite of self.an_element() |
| 559 | running ._test_category() . . . pass |
| 560 | running ._test_not_implemented_methods() . . . pass |
| 561 | running ._test_pickling() . . . pass |
| 562 | pass |
539 | 563 | running ._test_not_implemented_methods() . . . fail |
540 | 564 | Traceback (most recent call last): |
541 | 565 | ... |
-
diff --git a/sage/categories/examples/semigroups_cython.pyx b/sage/categories/examples/semigroups_cython.pyx
a
|
b
|
cdef class LeftZeroSemigroupElement(Elem |
130 | 130 | """ |
131 | 131 | return cmp(self._value, other._value) |
132 | 132 | |
133 | | def __getattr__(self, name): |
134 | | """ |
135 | | EXAMPLES:: |
136 | | |
137 | | sage: from sage.categories.examples.semigroups_cython import LeftZeroSemigroup |
138 | | sage: S = LeftZeroSemigroup() |
139 | | sage: x = S(3) |
140 | | sage: x.is_idempotent |
141 | | <bound method LeftZeroSemigroupElement.is_idempotent of 3> |
142 | | sage: x.is_idempotent() |
143 | | True |
144 | | """ |
145 | | result = getattr(self.parent().category().element_class, name) |
146 | | if isinstance(result, instancemethod): |
147 | | return instancemethod(result.im_func, self, self.__class__) |
148 | | elif isinstance(result, method_descriptor): |
149 | | return result # should bind the method descriptor to appropriate object |
150 | | else: |
151 | | return result |
152 | | |
153 | 133 | # Apparently, python looks for __mul__, __pow__, ... in the |
154 | 134 | # class of self rather than in self itself. No big deal, since |
155 | 135 | # those will usually be defined in a cython super class of |
… |
… |
class LeftZeroSemigroup(LeftZeroSemigrou |
229 | 209 | sage: TestSuite(S).run(verbose = True) |
230 | 210 | running ._test_an_element() . . . pass |
231 | 211 | running ._test_associativity() . . . pass |
232 | | running ._test_element_pickling() . . . pass |
| 212 | running ._test_category() . . . pass |
| 213 | running ._test_elements() . . . |
| 214 | Running the test suite of self.an_element() |
| 215 | running ._test_category() . . . pass |
| 216 | running ._test_not_implemented_methods() . . . pass |
| 217 | running ._test_pickling() . . . pass |
| 218 | pass |
233 | 219 | running ._test_not_implemented_methods() . . . pass |
234 | 220 | running ._test_pickling() . . . pass |
235 | 221 | running ._test_some_elements() . . . pass |
… |
… |
class LeftZeroSemigroup(LeftZeroSemigrou |
237 | 223 | That's really the only method which is obtained from the category ... :: |
238 | 224 | |
239 | 225 | sage: S(42).is_idempotent |
240 | | <bound method LeftZeroSemigroupElement.is_idempotent of 42> |
| 226 | <bound method IdempotentSemigroups.element_class.is_idempotent of 42> |
241 | 227 | sage: S(42).is_idempotent() |
242 | 228 | True |
243 | 229 | |
244 | | sage: S(42)._pow_ # how to bind it? |
| 230 | sage: S(42)._pow_ # todo: not implemented (how to bind it?) |
245 | 231 | <method '_pow_' of 'sage.categories.examples.semigroups_cython.IdempotentSemigroupsElement' objects> |
246 | 232 | sage: S(42)^10 # todo: not implemented (see __getattr__) |
247 | 233 | 42 |
248 | 234 | |
249 | | sage: S(42).is_idempotent_cpdef # how to bind it? |
| 235 | sage: S(42).is_idempotent_cpdef # todo: not implemented (how to bind it?) |
250 | 236 | <method 'is_idempotent_cpdef' of 'sage.categories.examples.semigroups_cython.IdempotentSemigroupsElement' objects> |
251 | 237 | sage: S(42).is_idempotent_cpdef() # todo: not implemented (see __getattr__) |
252 | 238 | True |
-
diff --git a/sage/categories/examples/sets_cat.py b/sage/categories/examples/sets_cat.py
a
|
b
|
class PrimeNumbers(UniqueRepresentation, |
58 | 58 | |
59 | 59 | sage: TestSuite(P).run(verbose=True) |
60 | 60 | running ._test_an_element() . . . pass |
61 | | running ._test_element_pickling() . . . pass |
| 61 | running ._test_category() . . . pass |
| 62 | running ._test_elements() . . . |
| 63 | Running the test suite of self.an_element() |
| 64 | running ._test_category() . . . pass |
| 65 | running ._test_not_implemented_methods() . . . pass |
| 66 | running ._test_pickling() . . . pass |
| 67 | pass |
62 | 68 | running ._test_not_implemented_methods() . . . pass |
63 | 69 | running ._test_pickling() . . . pass |
64 | 70 | running ._test_some_elements() . . . pass |
… |
… |
class PrimeNumbers_Inherits(PrimeNumbers |
325 | 331 | |
326 | 332 | sage: TestSuite(P).run(verbose=True) |
327 | 333 | running ._test_an_element() . . . pass |
328 | | running ._test_element_pickling() . . . pass |
| 334 | running ._test_category() . . . pass |
| 335 | running ._test_elements() . . . |
| 336 | Running the test suite of self.an_element() |
| 337 | running ._test_category() . . . pass |
| 338 | running ._test_not_implemented_methods() . . . pass |
| 339 | running ._test_pickling() . . . pass |
| 340 | pass |
329 | 341 | running ._test_not_implemented_methods() . . . pass |
330 | 342 | running ._test_pickling() . . . pass |
331 | 343 | running ._test_some_elements() . . . pass |
… |
… |
class PrimeNumbers_Wrapper(PrimeNumbers_ |
437 | 449 | |
438 | 450 | TESTS:: |
439 | 451 | |
440 | | sage: TestSuite(P).run(verbose=True) |
441 | | running ._test_an_element() . . . pass |
442 | | running ._test_element_pickling() . . . pass |
443 | | running ._test_not_implemented_methods() . . . pass |
444 | | running ._test_pickling() . . . pass |
445 | | running ._test_some_elements() . . . pass |
| 452 | sage: TestSuite(P).run() |
446 | 453 | """ |
447 | 454 | def __init__(self): |
448 | 455 | """ |
… |
… |
class PrimeNumbers_Facade(PrimeNumbers_A |
598 | 605 | |
599 | 606 | TESTS:: |
600 | 607 | |
601 | | sage: TestSuite(P).run(verbose=True) |
| 608 | sage: TestSuite(P).run(verbose = True) |
602 | 609 | running ._test_an_element() . . . pass |
603 | | running ._test_element_pickling() . . . pass |
| 610 | running ._test_category() . . . pass |
| 611 | running ._test_elements() . . . |
| 612 | Running the test suite of self.an_element() |
| 613 | running ._test_category() . . . pass |
| 614 | running ._test_not_implemented_methods() . . . pass |
| 615 | running ._test_pickling() . . . pass |
| 616 | pass |
604 | 617 | running ._test_not_implemented_methods() . . . pass |
605 | 618 | running ._test_pickling() . . . pass |
606 | 619 | running ._test_some_elements() . . . pass |
-
diff --git a/sage/categories/finite_semigroups.py b/sage/categories/finite_semigroups.py
a
|
b
|
class FiniteSemigroups(Category): |
41 | 41 | |
42 | 42 | sage: C = FiniteSemigroups() |
43 | 43 | sage: TestSuite(C).run(verbose = True) |
| 44 | running ._test_category() . . . pass |
44 | 45 | running ._test_not_implemented_methods() . . . pass |
45 | 46 | running ._test_pickling() . . . pass |
46 | 47 | |
-
diff --git a/sage/categories/finite_weyl_groups.py b/sage/categories/finite_weyl_groups.py
a
|
b
|
class FiniteWeylGroups(Category): |
33 | 33 | sage: TestSuite(W).run(verbose = "True") |
34 | 34 | running ._test_an_element() . . . pass |
35 | 35 | running ._test_associativity() . . . pass |
36 | | running ._test_element_pickling() . . . pass |
| 36 | running ._test_category() . . . pass |
| 37 | running ._test_elements() . . . |
| 38 | Running the test suite of self.an_element() |
| 39 | running ._test_category() . . . pass |
| 40 | running ._test_not_implemented_methods() . . . pass |
| 41 | running ._test_pickling() . . . pass |
| 42 | pass |
37 | 43 | running ._test_enumerated_set_contains() . . . pass |
38 | 44 | running ._test_enumerated_set_iter_cardinality() . . . pass |
39 | 45 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/hopf_algebras_with_basis.py b/sage/categories/hopf_algebras_with_basis.py
a
|
b
|
class HopfAlgebrasWithBasis(Category_ove |
69 | 69 | running ._test_additive_associativity() . . . pass |
70 | 70 | running ._test_an_element() . . . pass |
71 | 71 | running ._test_associativity() . . . pass |
72 | | running ._test_element_pickling() . . . pass |
| 72 | running ._test_category() . . . pass |
| 73 | running ._test_elements() . . . |
| 74 | Running the test suite of self.an_element() |
| 75 | running ._test_category() . . . pass |
| 76 | running ._test_not_implemented_methods() . . . pass |
| 77 | running ._test_pickling() . . . pass |
| 78 | pass |
73 | 79 | running ._test_not_implemented_methods() . . . pass |
74 | 80 | running ._test_one() . . . pass |
75 | 81 | running ._test_pickling() . . . pass |
-
diff --git a/sage/categories/modules_with_basis.py b/sage/categories/modules_with_basis.py
a
|
b
|
class ModuleMorphismByLinearity(Morphism |
500 | 500 | |
501 | 501 | TESTS:: |
502 | 502 | |
503 | | sage: TestSuite(phi).run() |
| 503 | sage: TestSuite(phi).run() # known issue |
| 504 | Failure in _test_category: |
| 505 | ... |
| 506 | The following tests failed: _test_category |
| 507 | |
| 508 | Analysis: ``phi`` does not inherit from the element class of |
| 509 | the category of its parent:: |
| 510 | |
| 511 | sage: isinstance(phi, phi.parent().category().element_class) |
| 512 | False |
| 513 | |
| 514 | To be fixed in the general morphism overhaul (#....), possibly |
| 515 | by making sure to create ``phi`` through its parent. |
| 516 | |
504 | 517 | """ |
505 | 518 | if codomain is None and hasattr(on_basis, 'codomain'): |
506 | 519 | codomain = on_basis.codomain() |
… |
… |
class DiagonalModuleMorphism(ModuleMorph |
630 | 643 | |
631 | 644 | sage: phi.__class__ |
632 | 645 | <class 'sage.categories.modules_with_basis.DiagonalModuleMorphism'> |
633 | | sage: TestSuite(phi).run() |
| 646 | sage: TestSuite(phi).run() # known issue; see ModuleMorphismByLinearity.__init__ |
| 647 | Failure in _test_category: |
| 648 | ... |
| 649 | The following tests failed: _test_category |
634 | 650 | """ |
635 | 651 | assert codomain is not None |
636 | 652 | assert domain.basis().keys() == codomain.basis().keys() |
-
diff --git a/sage/categories/primer.py b/sage/categories/primer.py
a
|
b
|
Generic tests |
335 | 335 | sage: TestSuite(S).run(verbose = True) |
336 | 336 | running ._test_an_element() . . . pass |
337 | 337 | running ._test_associativity() . . . pass |
338 | | running ._test_element_pickling() . . . pass |
| 338 | running ._test_category() . . . pass |
| 339 | running ._test_elements() . . . |
| 340 | Running the test suite of self.an_element() |
| 341 | running ._test_category() . . . pass |
| 342 | running ._test_not_implemented_methods() . . . pass |
| 343 | running ._test_pickling() . . . pass |
| 344 | pass |
339 | 345 | running ._test_enumerated_set_contains() . . . pass |
340 | 346 | running ._test_enumerated_set_iter_cardinality() . . . pass |
341 | 347 | running ._test_enumerated_set_iter_list() . . . pass |
-
diff --git a/sage/categories/semigroups.py b/sage/categories/semigroups.py
a
|
b
|
class Semigroups(Category): |
41 | 41 | |
42 | 42 | sage: C = Semigroups() |
43 | 43 | sage: TestSuite(C).run(verbose=True) |
| 44 | running ._test_category() . . . pass |
44 | 45 | running ._test_not_implemented_methods() . . . pass |
45 | 46 | running ._test_pickling() . . . pass |
46 | 47 | |
-
diff --git a/sage/categories/sets_cat.py b/sage/categories/sets_cat.py
a
|
b
|
Sets |
12 | 12 | #****************************************************************************** |
13 | 13 | |
14 | 14 | from sage.misc.cachefunc import cached_method |
| 15 | from sage.misc.sage_unittest import TestSuite |
15 | 16 | from sage.misc.abstract_method import abstract_method |
16 | 17 | from sage.misc.lazy_attribute import lazy_attribute |
17 | 18 | from sage.categories.category import Category, HomCategory |
… |
… |
class Sets(Category): |
67 | 68 | |
68 | 69 | sage: TestSuite(P).run(verbose=True) |
69 | 70 | running ._test_an_element() . . . pass |
70 | | running ._test_element_pickling() . . . pass |
| 71 | running ._test_category() . . . pass |
| 72 | running ._test_elements() . . . |
| 73 | Running the test suite of self.an_element() |
| 74 | running ._test_category() . . . pass |
| 75 | running ._test_not_implemented_methods() . . . pass |
| 76 | running ._test_pickling() . . . pass |
| 77 | pass |
71 | 78 | running ._test_not_implemented_methods() . . . pass |
72 | 79 | running ._test_pickling() . . . pass |
73 | 80 | running ._test_some_elements() . . . pass |
… |
… |
class Sets(Category): |
296 | 303 | AssertionError: self.an_element() is not in self |
297 | 304 | """ |
298 | 305 | tester = self._tester(**options) |
299 | | tester.assert_(self.an_element() in self, "self.an_element() is not in self") |
| 306 | an_element = self.an_element() |
| 307 | tester.assert_(an_element in self, "self.an_element() is not in self") |
| 308 | |
| 309 | def _test_elements(self, tester = None, **options): |
| 310 | """ |
| 311 | Run generic tests on element(s) of ``self``. |
| 312 | |
| 313 | See also: :class:`TestSuite`. |
| 314 | |
| 315 | EXAMPLES:: |
| 316 | |
| 317 | sage: C = Sets().example() |
| 318 | sage: C._test_elements(verbose = True) |
| 319 | <BLANKLINE> |
| 320 | Running the test suite of self.an_element() |
| 321 | running ._test_category() . . . pass |
| 322 | running ._test_not_implemented_methods() . . . pass |
| 323 | running ._test_pickling() . . . pass |
| 324 | <BLANKLINE> |
| 325 | |
| 326 | Debugging tip: in case of failure of this test, run instead: |
| 327 | |
| 328 | sage: TestSuite(C.an_element()).run() |
| 329 | |
| 330 | Let us now implement a parent whose elements cannot be pickled:: |
| 331 | |
| 332 | sage: from sage.categories.examples.sets_cat import PrimeNumbers |
| 333 | sage: class Bla(SageObject): pass |
| 334 | sage: class CCls(PrimeNumbers): |
| 335 | ... def an_element(self): |
| 336 | ... return Bla() |
| 337 | sage: CC = CCls() |
| 338 | sage: CC._test_elements() |
| 339 | Failure in _test_pickling: |
| 340 | ... |
| 341 | PicklingError: Can't pickle <class '__main__.Bla'>: attribute lookup __main__.Bla failed |
| 342 | ... |
| 343 | The following tests failed: _test_pickling |
| 344 | """ |
| 345 | # TODO: add native support for nested test suites to TestSuite |
| 346 | |
| 347 | # The intention is to raise an exception only if this is |
| 348 | # run as a sub-testsuite of a larger testsuite. |
| 349 | is_sub_testsuite = (tester is not None) |
| 350 | tester = self._tester(tester = tester, **options) |
| 351 | # Or do we want to run the test on some_elements? |
| 352 | an_element = self.an_element() |
| 353 | tester.info("\n Running the test suite of self.an_element()") |
| 354 | TestSuite(an_element).run(verbose = tester._verbose, prefix = tester._prefix+" ", |
| 355 | raise_on_failure = is_sub_testsuite) |
| 356 | tester.info(tester._prefix+" ", newline = False) |
300 | 357 | |
301 | 358 | def some_elements(self): |
302 | 359 | """ |
… |
… |
class Sets(Category): |
350 | 407 | for x in elements: |
351 | 408 | tester.assert_(x in self, "the object %s in self.some_elements() is not in self"%(x,)) |
352 | 409 | |
353 | | def _test_element_pickling(self, **options): |
354 | | """ |
355 | | Run pickling/unpickling tests for elements of this parent. |
356 | | |
357 | | EXAMPLES:: |
358 | | |
359 | | sage: C = Sets().example() |
360 | | sage: C._test_element_pickling() |
361 | | |
362 | | SEE ALSO: :class:`TestSuite`, :func:`dumps` :func:`loads` |
363 | | |
364 | | Let us now write a class whose elements cannot be pickled:: |
365 | | |
366 | | sage: from sage.categories.examples.sets_cat import PrimeNumbers |
367 | | sage: class Bla(SageObject): pass |
368 | | sage: class CCls(PrimeNumbers): |
369 | | ... def an_element(self): |
370 | | ... return Bla() |
371 | | sage: CC = CCls() |
372 | | sage: CC._test_element_pickling() |
373 | | Traceback (most recent call last): |
374 | | ... |
375 | | PicklingError: Can't pickle <class '__main__.Bla'>: attribute lookup __main__.Bla failed |
376 | | """ |
377 | | tester = self._tester(**options) |
378 | | from sage.misc.all import loads, dumps |
379 | | # if x is a SageObject, we could call x._test_pickling() instead |
380 | | x = self.an_element() |
381 | | tester.assertEqual(loads(dumps(x)), x) |
382 | | |
383 | 410 | class ElementMethods: |
384 | 411 | ##def equal(x,y): |
385 | 412 | ##def =(x,y): |
386 | | pass |
| 413 | |
| 414 | # Used by Element._test_category |
| 415 | _dummy_attribute = None |
387 | 416 | |
388 | 417 | class HomCategory(HomCategory): |
389 | 418 | pass |
-
diff --git a/sage/combinat/root_system/cartan_type.py b/sage/combinat/root_system/cartan_type.py
a
|
b
|
class CartanType_standard_finite(UniqueR |
1266 | 1266 | TESTS:: |
1267 | 1267 | |
1268 | 1268 | sage: TestSuite(ct).run(verbose = True) |
| 1269 | running ._test_category() . . . pass |
1269 | 1270 | running ._test_not_implemented_methods() . . . pass |
1270 | 1271 | running ._test_pickling() . . . pass |
1271 | 1272 | """ |
-
diff --git a/sage/combinat/root_system/weyl_characters.py b/sage/combinat/root_system/weyl_characters.py
a
|
b
|
class WeylCharacter(AlgebraElement): |
115 | 115 | |
116 | 116 | sage: R = WeylCharacterRing("B3", prefix = "R") |
117 | 117 | sage: r = R(1,1,0) |
118 | | sage: TestSuite(r).run() |
| 118 | sage: TestSuite(r).run(skip = "_test_category") |
119 | 119 | """ |
120 | 120 | AlgebraElement.__init__(self, A) |
121 | 121 | self._hdict = hdict |
… |
… |
class WeylCharacterRing_class(Algebra): |
621 | 621 | EXAMPLES:: |
622 | 622 | |
623 | 623 | sage: R = WeylCharacterRing(['A',3]) |
624 | | sage: TestSuite(R).run() |
| 624 | sage: TestSuite(R).run(skip = "_test_elements") # see #7922 |
625 | 625 | """ |
626 | 626 | sage.structure.parent_base.ParentWithBase.__init__(self, base_ring, category = Algebras(base_ring)) |
627 | 627 | |
… |
… |
class WeightRingElement(AlgebraElement): |
2215 | 2215 | |
2216 | 2216 | sage: A2 = WeylCharacterRing(['A',2]) |
2217 | 2217 | sage: a2 = WeightRing(A2) |
2218 | | sage: TestSuite(a2).run(skip = ["_test_element_pickling"]) # see #7922 |
| 2218 | sage: TestSuite(a2).run(skip = ["_test_elements"]) # see #7922 |
2219 | 2219 | """ |
2220 | 2220 | AlgebraElement.__init__(self, A) |
2221 | 2221 | self._mdict = mdict |
… |
… |
class WeightRing(Algebra): |
2503 | 2503 | |
2504 | 2504 | sage: R = WeylCharacterRing(['G',2], prefix = "R", base_ring = QQ) |
2505 | 2505 | sage: S = WeightRing(R, prefix = "S") |
2506 | | sage: TestSuite(S).run(skip = ["_test_element_pickling"]) # see #7922 |
| 2506 | sage: TestSuite(S).run(skip = ["_test_elements"]) # see #7922 |
2507 | 2507 | """ |
2508 | 2508 | self._parent = A |
2509 | 2509 | self._cartan_type = self._parent._cartan_type |
-
diff --git a/sage/combinat/sf/sf.py b/sage/combinat/sf/sf.py
a
|
b
|
class SymmetricFunctions(UniqueRepresent |
215 | 215 | |
216 | 216 | TESTS: |
217 | 217 | |
218 | | There are a lot of missing features for this abstract parent. But some tests do pass: |
| 218 | There are a lot of missing features for this abstract parent. But some tests do pass:: |
219 | 219 | |
220 | 220 | sage: TestSuite(Sym).run() |
221 | 221 | Failure ... |
222 | | The following tests failed: _test_additive_associativity, _test_an_element, _test_associativity, _test_element_pickling, _test_not_implemented_methods, _test_one, _test_prod, _test_some_elements, _test_zero |
223 | | |
| 222 | The following tests failed: _test_additive_associativity, _test_an_element, _test_associativity, _test_elements, _test_not_implemented_methods, _test_one, _test_prod, _test_some_elements, _test_zero |
224 | 223 | """ |
225 | 224 | assert(R in Rings()) |
226 | 225 | self._base = R # Won't be needed when CategoryObject won't override anymore base_ring |
-
diff --git a/sage/misc/nested_class_test.py b/sage/misc/nested_class_test.py
a
|
b
|
for categories), but deriving only from |
12 | 12 | sage: P = TestParent1() |
13 | 13 | sage: TestSuite(P).run() |
14 | 14 | Failure ... |
15 | | The following tests failed: _test_element_pickling, _test_pickling |
| 15 | The following tests failed: _test_elements, _test_pickling |
16 | 16 | |
17 | 17 | They actually need to be in the NestedClassMetaclass. However, due to |
18 | 18 | a technical detail, this is currently not directly supported:: |
-
diff --git a/sage/misc/sage_unittest.py b/sage/misc/sage_unittest.py
a
|
b
|
class TestSuite(object): |
27 | 27 | object, in alphabetic order:: |
28 | 28 | |
29 | 29 | sage: TestSuite(1).run(verbose = True) |
| 30 | running ._test_category() . . . pass |
30 | 31 | running ._test_not_implemented_methods() . . . pass |
31 | 32 | running ._test_pickling() . . . pass |
32 | 33 | |
… |
… |
class TestSuite(object): |
41 | 42 | sage: TestSuite(S).run(verbose = True) |
42 | 43 | running ._test_an_element() . . . pass |
43 | 44 | running ._test_associativity() . . . pass |
44 | | running ._test_element_pickling() . . . pass |
| 45 | running ._test_category() . . . pass |
| 46 | running ._test_elements() . . . |
| 47 | Running the test suite of self.an_element() |
| 48 | running ._test_category() . . . pass |
| 49 | running ._test_not_implemented_methods() . . . pass |
| 50 | running ._test_pickling() . . . pass |
| 51 | pass |
45 | 52 | running ._test_enumerated_set_contains() . . . pass |
46 | 53 | running ._test_enumerated_set_iter_cardinality() . . . pass |
47 | 54 | running ._test_enumerated_set_iter_list() . . . pass |
… |
… |
class TestSuite(object): |
53 | 60 | |
54 | 61 | sage: S._test_associativity() |
55 | 62 | |
| 63 | Debugging tip: in case of failure of some test, use `%pdb on` to |
| 64 | turn on automatic debugging on error. Run the failing test |
| 65 | independtly: the debugger will stop right where the first |
| 66 | assertion fails. Then, introspection can be used to analyse what |
| 67 | exactly the problem is. See also the ``catch = False`` option to |
| 68 | :meth:`.run`. |
| 69 | |
56 | 70 | When meaningful, one can further customize on which elements |
57 | 71 | the tests are run. Here, we use it to *prove* that the |
58 | 72 | multiplication is indeed associative, by running the test on |
… |
… |
class TestSuite(object): |
72 | 86 | run a :class:`TestSuite` on one of its instances in its doctest |
73 | 87 | (replacing the current ``loads(dumps(x))`` tests). |
74 | 88 | |
| 89 | Finally, running ``TestSuite`` on a standard Python object does |
| 90 | some basic sanity checks: |
| 91 | |
| 92 | sage: TestSuite(int(1)).run(verbose = True) |
| 93 | running ._test_pickling() . . . pass |
| 94 | |
75 | 95 | TODO: |
76 | 96 | |
77 | | - allow for customized behavior in case of failing assertion |
| 97 | - Allow for customized behavior in case of failing assertion |
78 | 98 | (warning, error, statistic accounting). |
79 | 99 | This involves reimplementing the methods fail / failIf / ... |
80 | 100 | of unittest.TestCase in InstanceTester |
… |
… |
class TestSuite(object): |
82 | 102 | - Don't catch the exceptions if ``TestSuite(..).run()`` is called |
83 | 103 | under the debugger, or with ``%pdb`` on (how to detect this? see |
84 | 104 | ``IPython.ipapi.get()``, ``IPython.Magic.shell.call_pdb``, ...) |
| 105 | In the mean time, see the ``catch=False`` option. |
85 | 106 | |
86 | 107 | - Run the tests according to the inheritance order, from most |
87 | 108 | generic to most specific, rather than alphabetically. Then, the |
… |
… |
class TestSuite(object): |
90 | 111 | |
91 | 112 | - Improve integration with doctests (statistics on failing/passing tests) |
92 | 113 | |
| 114 | - Add proper support for nested testsuites. |
| 115 | |
93 | 116 | - Integration with unittest: |
94 | 117 | Make TestSuite inherit from unittest.TestSuite? |
95 | 118 | Make ``.run(...)`` accept a result object |
… |
… |
class TestSuite(object): |
112 | 135 | sage: TestSuite(ZZ) |
113 | 136 | Test suite for Integer Ring |
114 | 137 | """ |
| 138 | from sage.structure.sage_object import SageObject |
| 139 | if not isinstance(instance, (SageObject,PythonObjectWithTests)): |
| 140 | instance = PythonObjectWithTests(instance) |
115 | 141 | self._instance = instance |
116 | 142 | |
117 | 143 | def __repr__(self): |
… |
… |
class TestSuite(object): |
124 | 150 | return "Test suite for %s"%self._instance |
125 | 151 | |
126 | 152 | |
127 | | def run(self, category = None, skip = [], **options): |
| 153 | def run(self, category = None, skip = [], catch = True, raise_on_failure = False, **options): |
128 | 154 | """ |
129 | 155 | Run all the tests from this test suite: |
130 | 156 | |
131 | 157 | INPUT: |
132 | 158 | |
133 | 159 | - ``category`` - a category; reserved for future use |
134 | | - ``skip` ` - a string or list (or iterable) of strings |
| 160 | - ``skip`` - a string or list (or iterable) of strings |
| 161 | - ``raise_on_failure`` - a boolean (default: False) |
| 162 | - ``catch` - a boolean (default: True) |
135 | 163 | |
136 | 164 | All other options are passed down to the individual tests. |
137 | 165 | |
… |
… |
class TestSuite(object): |
142 | 170 | We now use the ``verbose`` option:: |
143 | 171 | |
144 | 172 | sage: TestSuite(1).run(verbose = True) |
| 173 | running ._test_category() . . . pass |
145 | 174 | running ._test_not_implemented_methods() . . . pass |
146 | 175 | running ._test_pickling() . . . pass |
147 | 176 | |
148 | 177 | Some tests may be skipped using the ``skip`` option:: |
149 | 178 | |
150 | 179 | sage: TestSuite(1).run(verbose = True, skip ="_test_pickling") |
| 180 | running ._test_category() . . . pass |
151 | 181 | running ._test_not_implemented_methods() . . . pass |
152 | | sage: TestSuite(1).run(verbose = True, skip =["_test_pickling"]) |
| 182 | sage: TestSuite(1).run(verbose = True, skip =["_test_pickling", "_test_category"]) |
153 | 183 | running ._test_not_implemented_methods() . . . pass |
154 | 184 | |
155 | 185 | We now show (and test) some standard error reports:: |
… |
… |
class TestSuite(object): |
186 | 216 | AssertionError |
187 | 217 | ------------------------------------------------------------ |
188 | 218 | running ._test_c() . . . pass |
| 219 | running ._test_category() . . . pass |
189 | 220 | running ._test_d() . . . fail |
190 | 221 | Traceback (most recent call last): |
191 | 222 | ... |
… |
… |
class TestSuite(object): |
202 | 233 | File "/opt/sage/local/lib/python/site-packages/sage/misc/sage_unittest.py", line 183, in run |
203 | 234 | test_method(tester = tester) |
204 | 235 | |
| 236 | The ``catch=False`` option prevents ``TestSuite`` from |
| 237 | catching exceptions:: |
| 238 | |
| 239 | sage: TestSuite(Blah()).run(catch=False) |
| 240 | Traceback (most recent call last): |
| 241 | ... |
| 242 | File ..., in _test_b |
| 243 | def _test_b(self, tester): tester.fail() |
| 244 | ... |
| 245 | AssertionError |
| 246 | |
| 247 | In conjonction with ``%pdb on``, this allows for the debbuger |
| 248 | to jump directly to the first failure location. |
205 | 249 | """ |
206 | 250 | if type(skip) == str: |
207 | 251 | skip = [skip] |
208 | 252 | else: |
209 | 253 | skip = tuple(skip) |
210 | | tester = self._instance._tester(**options) |
| 254 | |
| 255 | # The class of exceptions that will be catched and reported; |
| 256 | # other exceptions will get trough. None catches nothing. |
| 257 | catch_exception = Exception if catch else None |
| 258 | |
| 259 | tester = instance_tester(self._instance, **options) |
211 | 260 | failed = [] |
212 | 261 | for method_name in dir(self._instance): |
213 | 262 | if method_name[0:6] == "_test_" and method_name not in skip: |
214 | 263 | # TODO: improve pretty printing |
215 | 264 | # could use the doc string of the test method? |
216 | | tester.info("running .%s() . . . "%method_name, newline = False) |
| 265 | tester.info(tester._prefix+"running .%s() . . . "%method_name, newline = False) |
217 | 266 | test_method = getattr(self._instance, method_name) |
218 | 267 | try: |
219 | 268 | test_method(tester = tester) |
220 | 269 | tester.info("pass") |
221 | | except: |
222 | | if tester._verbose: |
223 | | tester.info("fail") |
| 270 | except catch_exception as e: |
| 271 | failed.append(method_name) |
| 272 | if isinstance(e, TestSuiteFailure): |
| 273 | # The failure occured in a nested testsuite |
| 274 | # which has already reported the details of |
| 275 | # that failure |
| 276 | if not tester._verbose: |
| 277 | print tester._prefix+"Failure in %s"%method_name |
224 | 278 | else: |
225 | | print "Failure in %s:"%method_name |
226 | | traceback.print_exc(file = sys.stdout) |
227 | | print "-" * 60 |
228 | | failed.append(method_name) |
| 279 | if tester._verbose: |
| 280 | tester.info("fail") |
| 281 | else: |
| 282 | print tester._prefix+"Failure in %s:"%method_name |
| 283 | s = traceback.format_exc() |
| 284 | print tester._prefix + s.strip().replace("\n", "\n"+tester._prefix) |
| 285 | print tester._prefix + "-" * 60 |
229 | 286 | if len(failed) > 0: |
230 | | print "The following tests failed: %s"%(", ".join(failed)) |
| 287 | print tester._prefix+"The following tests failed: %s"%(", ".join(failed)) |
| 288 | if raise_on_failure: |
| 289 | raise TestSuiteFailure |
| 290 | |
| 291 | class TestSuiteFailure(AssertionError): |
| 292 | pass |
| 293 | |
| 294 | def instance_tester(instance, tester = None, **options): |
| 295 | """ |
| 296 | Returns a gadget attached to ``instance`` providing testing utilities. |
| 297 | |
| 298 | EXAMPLES:: |
| 299 | |
| 300 | sage: from sage.misc.sage_unittest import instance_tester |
| 301 | sage: tester = instance_tester(ZZ) |
| 302 | |
| 303 | sage: tester.assert_(1 == 1) |
| 304 | sage: tester.assert_(1 == 0) |
| 305 | Traceback (most recent call last): |
| 306 | ... |
| 307 | AssertionError |
| 308 | sage: tester.assert_(1 == 0, "this is expected to fail") |
| 309 | Traceback (most recent call last): |
| 310 | ... |
| 311 | AssertionError: this is expected to fail |
| 312 | |
| 313 | sage: tester.assertEquals(1, 1) |
| 314 | sage: tester.assertEquals(1, 0) |
| 315 | Traceback (most recent call last): |
| 316 | ... |
| 317 | AssertionError: 1 != 0 |
| 318 | |
| 319 | The available assertion testing facilities are the same as in |
| 320 | :class:`unittest.TestCase`, which see (actually, by a slight |
| 321 | abuse, tester is currently an instance of this class). |
| 322 | |
| 323 | TESTS:: |
| 324 | |
| 325 | sage: instance_tester(ZZ, tester = tester) is tester |
| 326 | True |
| 327 | """ |
| 328 | if tester is None: |
| 329 | return InstanceTester(instance, **options) |
| 330 | else: |
| 331 | assert len(options) == 0 |
| 332 | assert tester._instance is instance |
| 333 | return tester |
231 | 334 | |
232 | 335 | class InstanceTester(unittest.TestCase): |
233 | 336 | """ |
… |
… |
class InstanceTester(unittest.TestCase): |
245 | 348 | Testing utilities for Integer Ring |
246 | 349 | """ |
247 | 350 | |
248 | | def __init__(self, instance, elements = None, verbose = False, **options): |
| 351 | def __init__(self, instance, elements = None, verbose = False, prefix = "", **options): |
249 | 352 | """ |
250 | 353 | A gadget attached to an instance providing it with testing utilities. |
251 | 354 | |
… |
… |
class InstanceTester(unittest.TestCase): |
263 | 366 | self._instance = instance |
264 | 367 | self._verbose = verbose |
265 | 368 | self._elements = elements |
| 369 | self._prefix = prefix |
266 | 370 | |
267 | 371 | def runTest(self): |
268 | 372 | """ |
… |
… |
class InstanceTester(unittest.TestCase): |
341 | 445 | return self._instance.some_elements() |
342 | 446 | else: |
343 | 447 | return self._elements |
| 448 | |
| 449 | class PythonObjectWithTests(object): |
| 450 | """ |
| 451 | Utility class for running basis tests on a plain Python object |
| 452 | (that is not in SageObject). More test methods can be added here. |
| 453 | |
| 454 | EXAMPLES:: |
| 455 | |
| 456 | sage: TestSuite("bla").run() |
| 457 | |
| 458 | """ |
| 459 | def __init__(self, instance): |
| 460 | """ |
| 461 | EXAMPLES:: |
| 462 | |
| 463 | sage: from sage.misc.sage_unittest import PythonObjectWithTests |
| 464 | sage: x = PythonObjectWithTests(int(1)); x |
| 465 | <sage.misc.sage_unittest.PythonObjectWithTests object at ...> |
| 466 | sage: TestSuite(x).run() |
| 467 | """ |
| 468 | |
| 469 | self._instance = instance |
| 470 | |
| 471 | def _test_pickling(self, **options): |
| 472 | """ |
| 473 | Checks that the instance in self can be pickled and unpickled properly. |
| 474 | |
| 475 | EXAMPLES:: |
| 476 | |
| 477 | sage: from sage.misc.sage_unittest import PythonObjectWithTests |
| 478 | sage: PythonObjectWithTests(int(1))._test_pickling() |
| 479 | |
| 480 | SEE ALSO: :func:`dumps` :func:`loads` |
| 481 | """ |
| 482 | tester = instance_tester(self, **options) |
| 483 | from sage.misc.all import loads, dumps |
| 484 | tester.assertEqual(loads(dumps(self._instance)), self._instance) |
-
diff --git a/sage/modular/hecke/module.py b/sage/modular/hecke/module.py
a
|
b
|
class HeckeModule_free_module(HeckeModul |
471 | 471 | |
472 | 472 | sage: M = sage.modular.hecke.module.HeckeModule_free_module(QQ, 12, -4); M |
473 | 473 | <class 'sage.modular.hecke.module.HeckeModule_free_module_with_category'> |
474 | | sage: TestSuite(M).run(skip = ["_test_additive_associativity", "_test_an_element", "_test_element_pickling", "_test_pickling", "_test_some_elements", "_test_zero"]) # is this supposed to be an abstract parent without elements? |
| 474 | sage: TestSuite(M).run(skip = ["_test_additive_associativity", "_test_an_element", "_test_elements", "_test_pickling", "_test_some_elements", "_test_zero"]) # is this supposed to be an abstract parent without elements? |
475 | 475 | """ |
476 | 476 | HeckeModule_generic.__init__(self, base_ring, level) |
477 | 477 | self.__weight = weight |
-
diff --git a/sage/rings/number_field/class_group.py b/sage/rings/number_field/class_group.py
a
|
b
|
class ClassGroup(AbelianGroup_class): |
40 | 40 | |
41 | 41 | sage: G.category() |
42 | 42 | Category of groups |
43 | | sage: TestSuite(G).run() # todo: improve that! |
| 43 | sage: TestSuite(G).run() # see #7945 |
44 | 44 | Failure in _test_an_element: |
45 | 45 | ... |
46 | 46 | AssertionError: self.an_element() is not in self |
47 | 47 | ... |
48 | | The following tests failed: _test_an_element, _test_element_pickling, _test_inverse, _test_some_elements |
| 48 | The following tests failed: _test_an_element, _test_elements, _test_inverse, _test_some_elements |
49 | 49 | """ |
50 | 50 | self.__number_field = number_field |
51 | 51 | self.__gens = Sequence([FractionalIdealClass(x, self) for x in gens], immutable=True, |
-
diff --git a/sage/rings/residue_field.pyx b/sage/rings/residue_field.pyx
a
|
b
|
class ResidueField_generic(Field): |
305 | 305 | |
306 | 306 | TESTS:: |
307 | 307 | |
308 | | sage: TestSuite(k).run(skip = ["_test_element_pickling", "_test_pickling"]) # see #7929 |
309 | | sage: TestSuite(F).run(skip = ["_test_element_pickling", "_test_pickling"]) # see #7929 |
| 308 | sage: TestSuite(k).run(skip = ["_test_elements", "_test_pickling"]) # see #7929 |
| 309 | sage: TestSuite(F).run(skip = ["_test_elements", "_test_pickling"]) # see #7929 |
310 | 310 | """ |
311 | 311 | self.p = p |
312 | 312 | self.f = f |
-
diff --git a/sage/schemes/generic/scheme.py b/sage/schemes/generic/scheme.py
a
|
b
|
class Scheme(ParentWithBase): |
60 | 60 | sage: I = (x^2 - y^2)*R |
61 | 61 | sage: RmodI = R.quotient(I) |
62 | 62 | sage: X = Spec(RmodI) |
63 | | sage: TestSuite(X).run(skip = ["_test_an_element", "_test_element_pickling", "_test_some_elements"]) |
| 63 | sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements", "_test_some_elements", "_test_category"]) # See #7946 |
64 | 64 | |
65 | 65 | A scheme is in the category of all schemes over the base scheme of self:: |
66 | 66 | |
-
diff --git a/sage/schemes/generic/spec.py b/sage/schemes/generic/spec.py
a
|
b
|
class Spec(scheme.AffineScheme): |
47 | 47 | Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Rational Field |
48 | 48 | sage: X = Spec(PolynomialRing(GF(49,'a'), 3, 'x')); X |
49 | 49 | Spectrum of Multivariate Polynomial Ring in x0, x1, x2 over Finite Field in a of size 7^2 |
50 | | sage: loads(X.dumps()) == X |
51 | | True |
| 50 | sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements", "_test_some_elements", "_test_category"]) # see # 7946 |
| 51 | |
52 | 52 | sage: A = Spec(ZZ); B = Spec(ZZ) |
53 | 53 | sage: A is B |
54 | 54 | False |
-
diff --git a/sage/schemes/jacobians/abstract_jacobian.py b/sage/schemes/jacobians/abstract_jacobian.py
a
|
b
|
class Jacobian_generic(Scheme): |
75 | 75 | |
76 | 76 | Note: this is an abstract parent, so we skip element tests:: |
77 | 77 | |
78 | | sage: TestSuite(J).run(skip =["_test_an_element", "_test_element_pickling", "_test_some_elements"]) |
| 78 | sage: TestSuite(J).run(skip =["_test_an_element", "_test_elements", "_test_some_elements"]) |
79 | 79 | |
80 | 80 | :: |
81 | 81 | |
-
diff --git a/sage/structure/category_object.pyx b/sage/structure/category_object.pyx
a
|
b
|
cdef int bad_parent_warnings = 0 |
50 | 50 | |
51 | 51 | import generators |
52 | 52 | import sage_object |
53 | | from sage.categories.category import JoinCategory |
| 53 | from sage.categories.category import Category, JoinCategory |
54 | 54 | |
55 | 55 | def guess_category(obj): |
56 | 56 | # this should be obsolete if things declare their categories |
… |
… |
cdef class CategoryObject(sage_object.Sa |
157 | 157 | def category(self): |
158 | 158 | if self._category is None: |
159 | 159 | # COERCE TODO: we shouldn't need this |
160 | | from sage.categories.all import Objects |
| 160 | from sage.categories.objects import Objects |
161 | 161 | self._category = Objects() |
162 | 162 | return self._category |
163 | 163 | |
| 164 | def categories(self): |
| 165 | """ |
| 166 | EXAMPLES:: |
| 167 | |
| 168 | sage: ZZ.categories() |
| 169 | [Category of euclidean domains, |
| 170 | Category of principal ideal domains, |
| 171 | Category of gcd domains, |
| 172 | Category of integral domains, |
| 173 | Category of commutative rings, |
| 174 | Category of domains, |
| 175 | Category of rings, |
| 176 | Category of rngs, |
| 177 | Category of commutative additive groups, |
| 178 | Category of commutative additive monoids, |
| 179 | Category of commutative additive semigroups, |
| 180 | Category of monoids, |
| 181 | Category of semigroups, |
| 182 | Category of sets, |
| 183 | Category of objects] |
| 184 | """ |
| 185 | return self.category().all_super_categories() |
164 | 186 | |
165 | 187 | ############################################################################## |
166 | 188 | # Generators |
-
diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
a
|
b
|
import traceback |
181 | 181 | cdef MethodType |
182 | 182 | from types import MethodType |
183 | 183 | |
184 | | from sage.categories.sets_cat import Sets |
| 184 | from sage.categories.category import Category |
185 | 185 | from sage.structure.parent cimport Parent |
| 186 | from sage.structure.parent import is_extension_type |
186 | 187 | |
187 | 188 | # This classes uses element.pxd. To add data members, you |
188 | 189 | # must change that file. |
… |
… |
cdef class Element(sage_object.SageObjec |
433 | 434 | from sage.categories.all import Elements |
434 | 435 | return Elements(self._parent) |
435 | 436 | |
| 437 | |
| 438 | def _test_category(self, **options): |
| 439 | """ |
| 440 | Run generic tests on the method :meth:`.category`. |
| 441 | |
| 442 | See also: :class:`TestSuite`. |
| 443 | |
| 444 | EXAMPLES:: |
| 445 | |
| 446 | sage: 3._test_category() |
| 447 | |
| 448 | Let us now write a broken :meth:`.category` method:: |
| 449 | |
| 450 | sage: from sage.categories.examples.sets_cat import PrimeNumbers |
| 451 | sage: class CCls(PrimeNumbers): |
| 452 | ... def an_element(self): |
| 453 | ... return 18 |
| 454 | sage: CC = CCls() |
| 455 | sage: CC._test_an_element() |
| 456 | Traceback (most recent call last): |
| 457 | ... |
| 458 | AssertionError: self.an_element() is not in self |
| 459 | """ |
| 460 | from sage.categories.objects import Objects |
| 461 | tester = self._tester(**options) |
| 462 | sage_object.SageObject._test_category(self, tester = tester) |
| 463 | category = self.category() |
| 464 | # Tests that self inherits methods from the categories |
| 465 | if not is_extension_type(self.__class__): |
| 466 | # For usual Python classes, that should be done with |
| 467 | # standard inheritance |
| 468 | tester.assert_(isinstance(self, self.parent().category().element_class)) |
| 469 | else: |
| 470 | # For extension types we just check that inheritance |
| 471 | # occurs on a dummy attribute of Sets().ElementMethods |
| 472 | tester.assert_(hasattr(self, "_dummy_attribute")) |
| 473 | |
| 474 | |
436 | 475 | def parent(self, x=None): |
437 | 476 | """ |
438 | 477 | Returns parent of this element; or, if the optional argument x is |
-
diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
a
|
b
|
A simple example of registering coercion |
70 | 70 | cimport element |
71 | 71 | cimport sage.categories.morphism as morphism |
72 | 72 | cimport sage.categories.map as map |
| 73 | from sage.structure.sage_object import SageObject |
73 | 74 | from sage.misc.lazy_attribute import lazy_attribute |
74 | 75 | from sage.categories.sets_cat import Sets |
75 | 76 | from copy import copy |
… |
… |
cdef class Parent(category_object.Catego |
496 | 497 | self._category = Sets() |
497 | 498 | return self._category |
498 | 499 | |
499 | | def categories(self): |
| 500 | def _test_category(self, **options): |
500 | 501 | """ |
| 502 | Run generic tests on the method :meth:`.category`. |
| 503 | |
| 504 | See also: :class:`TestSuite`. |
| 505 | |
501 | 506 | EXAMPLES:: |
502 | 507 | |
503 | | sage: ZZ.categories() |
504 | | [Category of euclidean domains, |
505 | | Category of principal ideal domains, |
506 | | Category of gcd domains, |
507 | | Category of integral domains, |
508 | | Category of commutative rings, |
509 | | Category of domains, |
510 | | Category of rings, |
511 | | Category of rngs, |
512 | | Category of commutative additive groups, |
513 | | Category of commutative additive monoids, |
514 | | Category of commutative additive semigroups, |
515 | | Category of monoids, |
516 | | Category of semigroups, |
517 | | Category of sets, |
518 | | Category of objects] |
| 508 | sage: C = Sets().example() |
| 509 | sage: C._test_category() |
| 510 | |
| 511 | Let us now write a parent with broken categories: |
| 512 | |
| 513 | sage: class MyParent(Parent): |
| 514 | ... def __init__(self): |
| 515 | ... pass |
| 516 | sage: P = MyParent() |
| 517 | sage: P._test_category() |
| 518 | Traceback (most recent call last): |
| 519 | ... |
| 520 | AssertionError: category of self improperly initialized |
| 521 | |
| 522 | To fix this, :meth:`MyParent.__init__` should initialize the |
| 523 | category of ``self`` by calling :meth:`._init_category` or |
| 524 | ``Parent.__init__(self, category = ...)``. |
519 | 525 | """ |
520 | | return self.category().all_super_categories() |
| 526 | tester = self._tester(**options) |
| 527 | SageObject._test_category(self, tester = tester) |
| 528 | category = self.category() |
| 529 | tester.assert_(category.is_subcategory(Sets())) |
| 530 | # Tests that self inherits methods from the categories |
| 531 | if not is_extension_type(self.__class__): |
| 532 | # For usual Python classes, that should be done with |
| 533 | # standard inheritance |
| 534 | tester.assert_(isinstance(self, category.parent_class), |
| 535 | "category of self improperly initialized"%self) |
| 536 | else: |
| 537 | # For extension types we just check that inheritance |
| 538 | # occurs on one specific method. |
| 539 | # _test_an_element from Sets().ParentMethods is a good |
| 540 | # candidate because it's unlikely to be overriden in self. |
| 541 | tester.assert_(hasattr(self, "_test_an_element"), |
| 542 | "category of self improperly initialized"%self) |
521 | 543 | |
522 | 544 | cdef int init_coerce(self, bint warn=True) except -1: |
523 | 545 | if self._coerce_from_hash is None: |
… |
… |
cdef class Parent(category_object.Catego |
553 | 575 | running ._test_additive_associativity() . . . pass |
554 | 576 | running ._test_an_element() . . . pass |
555 | 577 | running ._test_associativity() . . . pass |
556 | | running ._test_element_pickling() . . . pass |
| 578 | running ._test_category() . . . pass |
| 579 | running ._test_elements() . . . |
| 580 | Running the test suite of self.an_element() |
| 581 | running ._test_category() . . . pass |
| 582 | running ._test_not_implemented_methods() . . . pass |
| 583 | running ._test_pickling() . . . pass |
| 584 | pass |
557 | 585 | running ._test_not_implemented_methods() . . . pass |
558 | 586 | running ._test_one() . . . pass |
559 | 587 | running ._test_pickling() . . . pass |
… |
… |
cdef class Parent(category_object.Catego |
583 | 611 | ['_test_additive_associativity', |
584 | 612 | '_test_an_element', |
585 | 613 | '_test_associativity', |
586 | | '_test_element_pickling', |
| 614 | '_test_category', |
| 615 | '_test_elements', |
587 | 616 | '_test_not_implemented_methods', |
588 | 617 | '_test_one', |
589 | | '_test_pickling', |
| 618 | '_test_pickling', |
590 | 619 | '_test_prod', |
591 | 620 | '_test_some_elements', |
592 | 621 | '_test_zero'] |
-
diff --git a/sage/structure/sage_object.pyx b/sage/structure/sage_object.pyx
a
|
b
|
cdef class SageObject: |
201 | 201 | from sage.categories.all import Objects |
202 | 202 | return Objects() |
203 | 203 | |
| 204 | def _test_category(self, **options): |
| 205 | """ |
| 206 | Run generic tests on the method :meth:`.category`. |
| 207 | |
| 208 | See also: :class:`TestSuite`. |
| 209 | |
| 210 | EXAMPLES:: |
| 211 | |
| 212 | sage: O = SageObject() |
| 213 | sage: O._test_category() |
| 214 | |
| 215 | Let us now write a broken :meth:`.category` method:: |
| 216 | |
| 217 | sage: class CCls(SageObject): |
| 218 | ... def category(self): |
| 219 | ... return 3 |
| 220 | sage: CC = CCls() |
| 221 | sage: CC._test_category() |
| 222 | Traceback (most recent call last): |
| 223 | ... |
| 224 | AssertionError |
| 225 | """ |
| 226 | from sage.categories.category import Category |
| 227 | from sage.categories.objects import Objects |
| 228 | tester = self._tester(**options) |
| 229 | category = self.category() |
| 230 | tester.assert_(isinstance(category, Category)) |
| 231 | tester.assert_(category.is_subcategory(Objects())) |
| 232 | tester.assert_(self in category) |
| 233 | |
204 | 234 | ## def category(self): |
205 | 235 | ## try: |
206 | 236 | ## return self.__category |
… |
… |
cdef class SageObject: |
215 | 245 | # Test framework |
216 | 246 | ############################################################################# |
217 | 247 | |
| 248 | def _tester(self, **options): |
| 249 | """ |
| 250 | Returns a gadget attached to ``self`` providing testing utilities. |
| 251 | |
| 252 | This is used by :class:`sage.misc.sage_unittest.TestSuite` and the |
| 253 | ``_test_*`` methods. |
| 254 | |
| 255 | EXAMPLES:: |
| 256 | |
| 257 | sage: tester = ZZ._tester() |
| 258 | |
| 259 | sage: tester.assert_(1 == 1) |
| 260 | sage: tester.assert_(1 == 0) |
| 261 | Traceback (most recent call last): |
| 262 | ... |
| 263 | AssertionError |
| 264 | sage: tester.assert_(1 == 0, "this is expected to fail") |
| 265 | Traceback (most recent call last): |
| 266 | ... |
| 267 | AssertionError: this is expected to fail |
| 268 | |
| 269 | sage: tester.assertEquals(1, 1) |
| 270 | sage: tester.assertEquals(1, 0) |
| 271 | Traceback (most recent call last): |
| 272 | ... |
| 273 | AssertionError: 1 != 0 |
| 274 | |
| 275 | The available assertion testing facilities are the same as in |
| 276 | :class:`unittest.TestCase`, which see (actually, by a slight |
| 277 | abuse, tester is currently an instance of this class). |
| 278 | |
| 279 | TESTS:: |
| 280 | |
| 281 | sage: ZZ._tester(tester = tester) is tester |
| 282 | True |
| 283 | """ |
| 284 | from sage.misc.sage_unittest import instance_tester |
| 285 | return instance_tester(self, **options) |
218 | 286 | |
219 | 287 | def _test_not_implemented_methods(self, **options): |
220 | 288 | """ |
… |
… |
cdef class SageObject: |
275 | 343 | from sage.misc.all import loads, dumps |
276 | 344 | tester.assertEqual(loads(dumps(self)), self) |
277 | 345 | |
278 | | def _tester(self, tester = None, **options): |
279 | | """ |
280 | | Returns a gadget attached to ``self`` providing testing utilities. |
281 | | |
282 | | This is used by :class:`sage.misc.sage_unittest.TestSuite` and the |
283 | | ``_test_*`` methods. |
284 | | |
285 | | EXAMPLES:: |
286 | | |
287 | | sage: tester = ZZ._tester() |
288 | | |
289 | | sage: tester.assert_(1 == 1) |
290 | | sage: tester.assert_(1 == 0) |
291 | | Traceback (most recent call last): |
292 | | ... |
293 | | AssertionError |
294 | | sage: tester.assert_(1 == 0, "this is expected to fail") |
295 | | Traceback (most recent call last): |
296 | | ... |
297 | | AssertionError: this is expected to fail |
298 | | |
299 | | sage: tester.assertEquals(1, 1) |
300 | | sage: tester.assertEquals(1, 0) |
301 | | Traceback (most recent call last): |
302 | | ... |
303 | | AssertionError: 1 != 0 |
304 | | |
305 | | The available assertion testing facilities are the same as in |
306 | | :class:`unittest.TestCase`, which see (actually, by a slight |
307 | | abuse, tester is currently an instance of this class). |
308 | | |
309 | | TESTS:: |
310 | | |
311 | | sage: ZZ._tester(tester = tester) is tester |
312 | | True |
313 | | """ |
314 | | if tester is None: |
315 | | from sage.misc.sage_unittest import InstanceTester |
316 | | return InstanceTester(self, **options) |
317 | | else: |
318 | | assert len(options) == 0 |
319 | | assert tester._instance is self |
320 | | return tester |
321 | | |
322 | 346 | ############################################################################# |
323 | 347 | # Coercions to interface objects |
324 | 348 | ############################################################################# |