This is based on a discussion from #4169
The basic question is might networkx benefit from the syntax flexibility provided by xdoctest?
My "The case for xdoctest in networkx" pitch is largely copied from the aforementioned thread:
I do think using xdoctest would be an overall improvement, and it would make writing / maintaining doctests much easier. I recently had to modify a PR to conform to the more restrictive builtin-doctest syntax. In the future I --- and perhaps others --- would prefer to utilize xdoctest syntax.
The main feature I'm making use of is "new-style got/want" tests, where print statements don't need to be broken up. For instance, the following works with xdoctest:
Example
-------
>>> open_to_close = {'{': '}', '(': ')', '[': ']'}
>>> seq = '({[[]]})[[][]]{{}}'
>>> all_decomp = generate_all_decomp(seq, open_to_close)
>>> node, *decomp = all_decomp[seq]
>>> pop_open, pop_close, head, tail, head_tail = decomp
>>> print('node = {!r}'.format(node))
>>> print('pop_open = {!r}'.format(pop_open))
>>> print('pop_close = {!r}'.format(pop_close))
>>> print('head = {!r}'.format(head))
>>> print('tail = {!r}'.format(tail))
>>> print('head_tail = {!r}'.format(head_tail))
node = '('
pop_open = '('
pop_close = ')'
head = '{[[]]}'
tail = '[[][]]{{}}'
head_tail = '{[[]]}[[][]]{{}}'
However, to refactor that to work with the builtin doctest module would require following each print statement with the text it produced:
Example
-------
>>> open_to_close = {'{': '}', '(': ')', '[': ']'}
>>> seq = '({[[]]})[[][]]{{}}'
>>> all_decomp = generate_all_decomp(seq, open_to_close)
>>> node, *decomp = all_decomp[seq]
>>> pop_open, pop_close, head, tail, head_tail = decomp
>>> print('node = {!r}'.format(node))
node = '('
>>> print('pop_open = {!r}'.format(pop_open))
pop_open = '('
>>> print('pop_close = {!r}'.format(pop_close))
pop_close = ')'
>>> print('head = {!r}'.format(head))
head = '{[[]]}'
>>> print('tail = {!r}'.format(tail))
tail = '[[][]]{{}}'
>>> print('head_tail = {!r}'.format(head_tail))
head_tail = '{[[]]}[[][]]{{}}'
Personally, I think the former is far more readable (you see a block of code that produces something and then you see the output as one single chunk, versus forcing humans to work like a REPL).
There are also minor issues with trailing whitespace causing got/want errors in the original doctest, the fact that any non-captured variable must provided with a "want" string, and the general issue of forcing the programmer to distinguish between lines that start a statement versus are continuations of previous statements.
For reference xdoctest is small, has no minimal dependencies, and is 100% compatible with the current structure of networks (in fact networkx is one of the main test-cases I used to ensure backwards compatibility when I wrote xdoctest), running pytest --xdoctest-modules --xdoctest-global-exec "import networkx as nx" will run all of the existing tests correctly.
This is based on a discussion from #4169
The basic question is might networkx benefit from the syntax flexibility provided by xdoctest?
My "The case for xdoctest in networkx" pitch is largely copied from the aforementioned thread:
I do think using xdoctest would be an overall improvement, and it would make writing / maintaining doctests much easier. I recently had to modify a PR to conform to the more restrictive builtin-doctest syntax. In the future I --- and perhaps others --- would prefer to utilize xdoctest syntax.
The main feature I'm making use of is "new-style got/want" tests, where print statements don't need to be broken up. For instance, the following works with xdoctest:
However, to refactor that to work with the builtin doctest module would require following each print statement with the text it produced:
Personally, I think the former is far more readable (you see a block of code that produces something and then you see the output as one single chunk, versus forcing humans to work like a REPL).
There are also minor issues with trailing whitespace causing got/want errors in the original doctest, the fact that any non-captured variable must provided with a "want" string, and the general issue of forcing the programmer to distinguish between lines that start a statement versus are continuations of previous statements.
For reference xdoctest is small, has no minimal dependencies, and is 100% compatible with the current structure of networks (in fact networkx is one of the main test-cases I used to ensure backwards compatibility when I wrote xdoctest), running
pytest --xdoctest-modules --xdoctest-global-exec "import networkx as nx"will run all of the existing tests correctly.