New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
megatest: CI should not compile/run files individually, could speedup CI by 15X #9581
Comments
In my test-merging PRs I'm doing exactly that where possible, but there are (lots of) places where |
that's great, I saw that
can you give me a typical (not extreme) example of such a case ? it should almost always be possible (for runtime echo at least; compile time is only sometimes possible) eg: proc foo()=
for i in 0..<3:
echo bar(i) => proc foo()=
var msg = ""
for i in 0..<3:
msg.add $bar(i)
doAssert msg == ... or even putting |
tcomputedgoto comes to mind. |
see #9597 ; I'm using tcomputedgoto.nim as 1st example of test transformed to doAssert in that PR |
So in other words, you automate what @narimiran did but tests can stay small for individual testing during development. I like it. |
/cc @Araq @narimiran how about the following then, which works regardless a test has a discard section or just uses doAssert (excluding tests that are intended to fail with compiler error, see footnote)
echo "testrunner_before test1.nim"
import "patho/test1"
echo "testrunner_after test1.nim"
echo "testrunner_before test2.nim"
import "patho/test2"
echo "testrunner_after test2.nim"
...
footnotes[1] regular test meaning: the test is expected to succeed, ie it doesn't expect it to fail with a specific compiler error (and we can reuse logic in testament by parsing the discard test section for that) noteif for some reason we don't want to stop on 1st error, we can convert tests from this form: discard """
...
"""
echo "foobar"
... to this: discard """
...
"""
proc main=
echo "foobar" and adjust import "patho/test1"
import "patho/test2"
...
var numFailures = 0
for test in (test1, test2,...):
try:
echo "testrunner_before " & $test
test.main()
except:
numFailures.inc # add other failure info for test stats generation if needed
finally:
echo "testrunner_after " & $test
# then report success/failures based on numFailures and above logic based on `Table[testName, testOutput]` EDIThmm, I just tried, one issue is that EDITok I think i found a solution, stay tuned |
update: a new module testament/runall.nim collects all tests and generates 1 wrapper per test (eg /tmp/D20181117T141313/trunall_0_tests_stdlib_tstrset.nim) and 1 module that aggregates all wrappers: /tmp/D20181117T141313/z01.nim:
I ran into other issues while doing that, eg:
but overall this works. for the tests in tests/stdlib (minus a blacklist of 4 files, to avoid above issue), compiling/running tests individually took 75 seconds, vs 13 seconds for compiling/running the aggregate; and stdout delimits when a module starts/ends thanks to the wrapper trick I used, from that we can compare against |
This has been implemented and merged. Speedups are not that great but for different reasons we can address later. |
/cc @Araq
any thoughts? |
Travis spends most of its time in |
btw just edited numbers above, it's not TOO bad: 34 seconds vs 74 seconds using a more focused comparison |
proposal
when isMainModule
blocks bywhen isMainModule or defined(testing)
for all files we want to test in testamenttest_all.nim
(not checked in) that imports all files we want to test in testament, minus a blacklistnim c -r test_all.nim
proof of concept
test_all.nim
versus ~50 seconds for compiling/running the files individuallyThat's a ~15X speedup, but the speedup would be even larger when aggregating more files; right now it aggregates all files run by the
lib
category, ie:(~91 files minus a blacklist of a 4 files that I commented out because it would lead to circular dependencies)
note
this is related to allow
import
insideblock
: makes N runnableExamples run N x faster, minimizes scope pollution · Issue #9300 · nim-lang/Nim in 1 aspect (compiling a single file instead of multiple files)will that "hide" some bugs?
I doubt it would, if anything running
test_all.nim
should expose more bugs rather than less bugs.Furthermore we can always add individual files if we ever discover ones that are only exhibited if they're run in isolation as opposed to via test_all.nim
A "light" version of this proposal is to first run test_all.nim, and if it passes, run the rest as we already do; the benefit being it'll fail early after 3 seconds instead of after XX seconds after the nth file fails.
what about different compiler options?
just generate several
test_all_{my_hashed_option}.nim
, one per unique compiler flags we're currently testing; eg:if we currently run files f1, f2 with flags a and files f3,f4,f5 with flags b, we'll have test_all_a importing f1,f2 and test_all_b importing f3,f4,f5
what about files with
discard """
blocks?we can focus on the ones which just echo some output, and make these use
doAssert
which is a better practice anyways.other files (eg that test compile errors) could be left as-is
The text was updated successfully, but these errors were encountered: