Jldoctest: number of elements printed for array

In a docstring like:

```jldoctest
julia> x = rand(1000)
1000-element Vector{Float64}:
 0.9193285028224774
 0.35444797029663266
 0.1201916693868853
 0.35371426411293694
 0.11668489865605236
 0.6506991967008628
 ⋮
 0.5180636146804571
 0.3354691171077989
 0.046577899510561904
 0.5993088546568675
 0.3926367429008284
 0.7955460631376658
```#

Is there a way to set the number of elements of the array to be printed or tested? Or make the test not fail if the output has fewer or more elements than what is printed (assuming that
the first and last elements match)?

This is the kind of output I’m talking about:

│ Expected output:
│ 
│ 584-element Vector{Tuple{Int64, Int64, Float64}}:
│  (1, 12, 7.360804915224965)
│  (1, 13, 7.017762962654125)
│  ⋮
│  (50, 37, 7.546490310071297)
│  (50, 39, 3.900154099519657)
│ 
│   diff =
│    584-element Vector{Tuple{Int64, Int64, Float64}}:
│     (1, 12, 7.360804915224965)
│     (1, 13, 7.017762962654125)
│     (1, 24, 7.976895636774997)
│     (1, 29, 3.177028328485598)
│     (1, 44, 5.394713986857875)
│     (1, 45, 5.4248765884580274)
│     (1, 11, 4.088651856052312)
│     (1, 17, 5.93977280710298)
│     (1, 30, 2.457228927063981)
│     (1, 28, 6.853834401267658)
│     ⋮
│     (50, 3, 7.232267901564487)
│     (50, 10, 3.9736202636890203)
│     (50, 27, 6.257296620746054)
│     (50, 32, 3.1099665593057426)
│     (50, 33, 2.919291694915052)
│     (50, 35, 5.043227240567294)
│     (50, 20, 6.995405134800987)
│     (50, 37, 7.546490310071297)
│     (50, 39, 3.900154099519657)
└ @ Documenter ~/.julia/dev/CellListMap/src/neighborlists.jl:568

(these tests fail because of the number of elements, the floating point precision is being filtered out).

20 elements, as it is expected, is too much, makes reading the docstring cumbersome.

Hi!

Probably doctest filtering is what you need. Basically, you define a regular expression that gets replaced both on expected and evaluated inputs, and after that they are compared.

In your case filter = r"(.*)\n(.*)\n(.*)\n[.\n]*(.*)\n(.*)" => s"\1\n\2\n\3\n\4\n\5\n" might do the thing (keep 3 first and 2 last lines, ignore all that remains; you might need some more regex trickery here).

1 Like

I which we could (can we?) pass general functions to filter the results. Regex trickery is definitely not my thing, and I just get stuck even with the simpler things.

(and it seems not be the thing of chatgpt either, it has failed so far for me in this one).

In a @meta setup block you should be able to control this by setting the displaysize option, e.g.:

julia> Base.active_repl.options.iocontext[:displaysize] = (10,80);

julia> [1:1000;]
1000-element Vector{Int64}:
    1
    2
    3
    ⋮
  999
 1000

julia> Base.active_repl.options.iocontext[:displaysize] = (5,80);

julia> [1:1000;]
1000-element Vector{Int64}:
 ⋮

assuming Documenter.jl uses Base.active_repl’s display, or there is some other way to control the IOContext that it uses.

Unfortunately it seems to ignore that. I’ve tried it.

Also, I’m willing to have that in docstrings, so I’m not sure those meta blocks will be considered when the user is just navigating the help> entries.

I understand the motivation behind this, but in the first place, the doctest is to ensure that the documentation matches the actual results.
If you don’t want to show (and check) some data, shouldn’t you write such example codes?

I mean:

julia> x[end-1:end] # The last two elements indicate the ...
2-element Vector{Float64}:
 0.3926367429008284
 0.7955460631376658
1 Like

Doc tests are the only place where I can test show methods with ease. Also, they are checked for consistency, and don’t become outdated, as example codes do. This is why having them, even if somehow filtered, is better than having example codes.

Also, the number of output lines of an array is an arbitrary parameter of the current display section, in some sense I think that the default behavior of doc tests should be matching what is displayed in the test, not any specific number of lines.

That specifically does not interest me, because the number of elements of the a array is a meaningful parameter. (and I don’t want an example to artificially slice or compute the length of the output).

This is off-topic, but if you are customizing show (or print), you should write explicit tests for it. That may be tedious (since different versions of julia have different styles, such as whether to include spaces, use aliases, etc.), but not difficult.

You noted that it makes sense to show the last element. If it has no value to the user (not you), there is no need to indicate it.

julia> summary(x)
"1000-element Vector{Float64}"

There is also the block-level-setup-code. Many docstrings use it and unfortunately we have to accept its redundancy (for now).
I do not know how to change the IO context.

In the first place, there is basically no functionality for docstrings to change with the user context. There are a few tricky ways, but they are more tricky than the Regex stuff.

That, or suggesting to call length, in an example, defeats the purpose of the example. It should just look as something the user will actually do.

Exactly that, but it would be a waste of time to write all the machinery to check the output of a show method to not use it in doc tests. That’s exactly why I would like to provide custom functions to the filter option. It would be a gain-gain situation.

I prefer examples to be minimalistic, which is easier to understand, than to be practical.
For example, pitfalls should be shown in examples, but that does not mean that the document writer wants the user to actually fall into the pitfalls.
If there is a wide gap between the simplicity and practicality, a practical tutorial article or notebook would be better.
This is a matter of values, not a discussion here.

There is an open issue: Controlling output text width in doctests · Issue #942 · JuliaDocs/Documenter.jl · GitHub — sounds like you can maybe use the LINES environment variable in docs/make.jl.

1 Like