test: Check return code, stdout, stderr of (almost) every example
Runs each of the files ending in '.js' in the examples directory or
a subdirectory thereof via node. Verifies the return code is normal
for each one. Compares stdout and stderr to reference copies.
As requested in #2264 (hopefully this can be a first step in clearing that and/or #2279 out of the PR queue). Some caveats that should be considered in review of this PR:
- I did not check that the results of all of the examples were sensible; if they ran, I simply took their current output as the reference.
- Please someone check that I fixed the non-operational
examples/advanced/custom_argument_parsing.jsin the correct way (it's quite unclear to me how one is supposed to create a subscope in user code (as opposed to internally within mathjs, where it is easy to import utils/scope.js).) Do I even need to make a copy of the scope I get in the raw function, as the document says it's already a shallow copy of the ambient scope? (i.e. can I set the specified variable in scope and dispense with the creation of fnScope altogether? I verified that it produced the same values if I did it that way, but I wasn't sure it was truly "safe" to the point where it's OK for the example to show doing things that way.) -
node examples/advanced/custom_loading.jsdidn't actually run at all, since by defaultnodedoesn't support import. So I renamed this file tocustom_loading.mjs(as it seems to be a module anyway) and then it's ignored by the test harness I have added. Problem solved ;-) Seriously, if there's a way to add a custom test for this one in examples.test.js, please guide me. Thanks. - There is an issue with
examples/import.js. I assumed that on the automated test machine, numbers and numeric would not be installed. So I used as the reference the output when these are not installed. That's all fine, but it means importing these external packages is not tested. If it should be, what should I do? I didn't think that having a test install a package would be a good idea, as it will then be too easy for these packages to end up checked in as dependencies of mathjs, which they are not. So should I just leave this be or should we try to engineer a specific test for importing external packages into mathjs? - I didn't see any convenient way to test
examples/advanced/web_serverbut thats a sub-sub-directory and so ignored by my harness. Again problem solved ;-) and again if there is a suggestion on a custom test for this stuff, please let me know. - I didn't even try to come up with a way to test the things in
examples/browser. There are no.jsfiles so the harness doesn't care. If there is a reasonable way to test them, let me know and I will add another harness just for them.
Anyhow, these comprise a really solid putting of mathjs through its paces, so hopefully what's there in this PR will be helpful in the future. (I am thinking also of writing a test in a separate PR which checks the output of every example in every embedded-docs help against a reference copy as well, as that should be pretty complete, too. There's a fair amount of overlap there with the unit tests, but also a fair amount of unique examples, and so it seems like we may as well use them.)
Happy to update this to latest mathjs develop, but need guidance on the many questions above.
I'm not sure how I missed this PR before, sorry for not looking into it before.
- I think this is a good start. In a second interation, we can store a snapshot of the correct output and compare against that if we want.
- Your change works I think, though this is probably not the most efficient as we copy all contents from
scopeintofnScope, and also, if we would change something inscopeafterwards, it's not reflected infnScope. It would be nice to implement anew MultiMap(fnScope, scope)utility which reads values iterating over all provides scopes, and writes values into the first provided scope. - Renaming to
.mjsmakes sense. The example working out of the box requires changing the import from'../../'to'../../lib/esm/index.js', I've fixed that example indevelopnow (see also #2144). - I can look into why this example fails to run, I'm not sure. Maybe because of the
require(...)statements halfway the file inside a try/catch block? (if that is the reason, maybe await import(...) could help out). - Yes, please ignore this one
- We would have to open these examples in a headless browser. That may require quite some work. Let's address that separately ok to keep this PR limited?
Sorry about the delay in getting back on this, I've been focused on Pocomath and/or the TypeScript experiments.
- Well, this commit does include snapshots of the output of each of the examples that ran. But I did not look through them manually to make sure they are all as desired. Maybe someone should before we commit them as the "correct" output?
- My apologies, but I am confused by your response here. What/how could
scopechange so that it wouldn't be reflected infnScope? Should I leave the code as is, or should I change it to just setxinscoperather than bothering to make thefnScopecopy? - I will take another look at this one on top of current develop and see if I can make it a working test.
- It doesn't fail to run, it just doesn't do much because neither 'numbers' or 'numeric' is installed. I didn't see how it was safe for the test to install modules, because then I thought they might get checked in to the mathjs repository, etc. Any suggestions on how to make this a test with real behavior, or should I just skip this one?
- Check.
- Check.
Thanks for further guidance.
- Ok I'll look though all the outputs to double check
- Hmmm, that is a good point. It can indeed not happen that there are changes made in
scopethat are not reflected infnScopesince the map is copied with every execution of the function. Ok nevermind, it's maybe not the most efficient solution but let's not over engineer this example and just keep it as is with youronst fnScope = new Map(scope). - 👍
- I would say let's just skip the example for now.
OK, I think we are clear on all of the points. I will try to move this back toward being merge-ready.