-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Create unit tests in Lua #2145
Comments
I strongly agree. A short research brought up the following page: lua-users.org/wiki/UnitTesting I would also like to include a check for required module(s) in each test or testfile so they could be marked appropriately in the results if the prerequisites fail. (or not be executed at all). To make sure that arbitrary sets of tests can be run by individuals I could imagine to have a naming schema (like "test-MyFavoriteTest") and a script that runs all matching files. just my 2c |
And
👍
I believe it's important to keep the execution & preparation effort minimal. Copy a single file to device and run it. If each test checks whether the required module is available I don't see the need for arbitrary sets. I have a few ideas how to improve this but I prefer to see working software rather than discussing the perfect solution for weeks and months 😉 |
Marcel, there is already an established test suite for standard Lua and I use it quite a lot for stress testing host variants of my build, e.g. the LCD and the current LFS patches as well as my 5.3 work. The main issue is that it's got far too big a footprint to use on standard NodeMCU builds. Having an LFS will help a lot here, plus a robust Lua provisioning system to download the test overlays. |
Nothing fancy, but I did experiment doing a minimal test framework that works on the nodemcu: https://github.com/luismfonseca/nodemcu-mispec |
Thanks Luís, I knew that there's something like this out there but I didn't remember who of the NodeMCU community brought it up earlier. It pretty much looks what I had in mind. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I think the more we are leaning towards Lua modules instead of C modules the more relevant this topic becomes. |
May I suggest running a test framework on a PC with access to a NodeMCU
through [RPC](https://github.com/ildar/tango/blob/master/README-NodeMCU.md)?
I like `busted` and it's already usable to test a node.
|
@ildar I think it better to test over the serial link than via the network. Fewer things that need to come up first and everything can be driven by something as straightforward as |
What we really need to get here is the Lua VM and the integration with NodeMCU. I will be the main user. I just don't see our typical IoT developers interested in something like this for IoT apps themselves. Perhaps professional orgs like DiUS and @jmattsson might be interested. So as @nwf suggests I feel something like the Lua test suite driven over a UART interface will be a better starter. |
I've found any sort of testing of embedded devices to generally be cumbersome, tedious and/or error prone. I'd certainly be interested in seeing something in this area, but I don't have much to contribute at this point. Past experience with other embedded environments would suggest that control over serial is the most flexible and reliable option, since often you'll want to test network attach/detach and various networking error conditions. I should mention that in the IDF on the ESP32, Espressif has included a unit testing framework. I have not looked at it other than to note that it is there. I might warrant a quick look at least. |
The other reason for using the UART is that it avoids depending on the network stack which is complex and complicated because of all of the other network housekeeping tasks that need to go on. A big component of the standard Lua tests ensure that the Lua VM can resiliently deal with memory exhaustion. As any ESP developer will tell you: in general memory exhaustion means death because stacks like LwIP don't currently use the Lua allocator so we can't gracefully recover from out-of-heap when the exhaustion occurs in the network stack. |
If RPC idea isn't yet fully denied I think that adding Tango server for
NodeMCU with serial communication is like ~5 minutes. And 5 minutes more to
add serial transport to PC client. Not a big deal!
|
That sounds like a good idea. How about a non-trivial example of it in use? |
Examples aren't numerous yet:
1. [basic (standard) Tango example](https://github.com/ildar/tango/blob/master/spec/tango_client_spec.lua) works just fine;
2. [basic hardware access test](https://github.com/ildar/esp-pirate/blob/master/spec/nodemcu_hwacess_spec.lua) works;
3. not-trivial app WIP: https://github.com/ildar/esp-pirate/
It smells offtopic here so I suggest moving to #2814 or esp-pirate if appropriate for continuation.
|
@marcelstoer @luismfonseca @TerryE
|
@marcelstoer @luismfonseca @TerryE Tests would be named OK I would really like someone to have an opinion. So please If you don't think this is a good idea tell me now, so I won't do this for the bin. |
Have you seen my dev-lua53-2:app/lua53/host/tests. These hammer the Lua core VM. The problem with testing most modules is that you need the right hardware to be correctly integrated with an ESP module before you can sensibly execute tests. Even with the core modules which don't require addition GPIO-connected H/W we still need other test listeners/responders to execute meaningful tests. We could use the same approach with some sort of RPC to a host or RPi script to do equivalent on-ESP tests. |
I think (but am not volunteering, so my $0.02 doesn't count for much more than that) that the best approach for testing is to have a standard nodemcu test environment, which includes 802.11 access, and an UART would give us the truly independent modules ( The script should take arguments for network setup, but probably we should expect to join existing infrastructure using WPA(2)-PSK. Such network connectivity lets us test at least As to the rest... we might be needing a more comprehensive test environment. |
I have a strong opinion (as expressed in #516 and this issue) but a pragmatic one. Any test is better than none! This embedded / micro controller environment is quite far from what I'm used to in terms of CI & CD in my comfy enterprise-backend-and-frontend-system-world. Of course, the challenges are unique if you can't abstract the hardware. However, as #2928 has shown we currently don't even ensure that the code we release compiles in all (expected) cases. nodemcu-mispec, and its gambiarra heritage, looks really nice. I like fluid APIs. You can see that it was likely influence by how you write JavaScript tests these days. So yes to
However, form follows function. Any other test "framework" that gets the job done would probably also be ok. Again, any test is better than none! And of course I fully support the ideas described by @nwf. I feel they're in line with what I (intended to) describe in this issue's initial comment. |
Marcel, doing this properly would take about 4-6 months of solid developer contribution. Take this #2928 issue as an example of what you infer that such a capability would have prevented this bug. This was a failure in a build variant enabled by I have already included the Lua Test Suites in Lua53 build (and that you don't even mention). This has about 10K test vectors covering the core Lua engine. It took me about 5 days solid slog to clear this and I found ~5 genuine implementation bugs in the process. I also had to validly change dozens of tests to accommodate valid differences between the NodeMCU and standard Lua environments. But this is only for one host environment, and not for ~100 target ones. Let's not make the mistake of doing this bottom-up. We need to be confident that we can resource and create a minimum capability that has a net benefit to the project. We need this confidence before we should even begin. So what is that minimum capability? Surely the first step is for someone to prepare a design spec for the whole end-to-end test system and then we can do a consensus estimate of the work involved. Once we have resource identified to is willing to commit to resource this, only then we should proceed. In the meantime are you or Gregor prepared to draft a spec of what you envision as the minimum capability. If we can't resource writing the spec then we certainly can't resource implementing it. |
Ok let me try to sketch the different approaches mentioned in this and other bugs:
Having a combination of 1 and 4 would allow for automated testing of different firmware builds (flash/download/test/report) and casual running of only some tests on the device. That way the test logic would stay on the ESP, allowing also for time sensitive operations and even blind spots where there is no connection to the host due to a test. Since both nodemcu-mispec and gambiarra seem not to be maintained we could take either one and adapt it as we need. I like the concept of passing a I haven't looked into the other parts, so no comment here. So we should decide what we want as final solution and then identify the steps with the most benefit for the project and do these first. |
Gregor, take this So to get decent coverage of the 20 options and module permutations we might need perhaps 100 different make subsets; certainly more than 10 and probably less than 1,000. For each build a different subset of remote tests would be applicable. We would really need a dedicated test system for example an RPi4 + USB3 SSD + one or more USB connected Wemos D1 Minis. Whilst it would be impractical to try to test all H/W we should at least test minimal GPIO, I2C and say OW functionality, so we would need a small custom board on the D1 Mini. This system could to a release check by cycling around the, say, 100 makes and for each download the firmware and run the subset of tests that would apply to that build config. This would take about perhaps 4hrs elapsed for such an RPi4 config. At the moment one of my RPis hosts my luac.cross service and it runs a batch script once a day to interrogate the current SHA1 for The challenge in all of this isn't procuring the H/W or cobbling together the test stack. On this last we do have to be careful because whatever the ESP-end is, we need to make sure that the selected stack leaves enough RAM resources left to do usable testing. The cost and the value is creating an adequate test vector, all of the test stubs and the PCM (Permitted Configuration Matrix) that links these together. This is the major exercise; it is many months of engineer effort. If we don't do this, then we will end up with a toy system that has not true value. |
I'm pretty much on the same page as Terry here. Having the ability to run tests against/on hardware is great, but it's a major effort, and even at $work we often make the call that it isn't worth the investment. I'll add one more requirement to the list as well - whatever is chosen (if any), needs to be possible to run locally. If someone pushes a change that breaks the test, they need to be able to easily replicate the test setup so they can debug locally. Throwing random changes at Travis and seeing what works, especially with a high turn-around time like testing-on-hardware does (even in relatively simple setups), is just not feasible, and would be a net loss in my experience. Before diving in, we really do need to have a clear goal in mind that's realistic, and isn't going to end up costing us more time than it gains us. |
I'm sure many here already know this book, but for those who don't:
James W. Grenning "Test Driven Development for Embedded C"
I don't say it's revolutionary but one definitely can widen his/her POV
looking at the problem with author's eyes.
|
what is the current understanding of how to test async methods? or is there any? i did some mocking of net, tmr and wifi modules among others in pure lua (nodemcu-lua-mocks) so one can unit test app code against it. but i'm not overly happy with the current outcome. |
The tl;dr is that it is f***ing complicated. Most scripting / test frameworks are intrinsically procedural. You really need some form of event-driven framework to test an event-driven application. I think I'll be dead before we have canned best practice for this one 🤣 |
i've just poke at LTS (5.3.4) and saw assert use in lua tests and opentests c-module. |
@fikin Nikolay, read through #2917, and back through the recent comments in this issue. As I said above I am using a tweaked version of the Lua Test Suite which I first run on the PC version of NodeMCU. OK, this is built around luac.c and a small subset of libraries (string, table, debug, coroutine, math, utf8, LFS, os and io). It's not a full interactive system but you can enter the Lua execution VM using the I am currently debugging some issue in the new LFS code paths unique to ESP, but once I've punched through this I've got a test suite of 30 LFS images which I will be running on-ESP. To do, but in the next day or so. I don't understand what you mean by opentests (and neither does Gooogle). |
opentests -> i'm referring to https://www.lua.org/tests/lua-5.3.4-tests.tar.gz, ltests/ folder, containing c-module tests. or is that module called something else? |
As in app/lua53/host/tests (that's the current version that will go into |
I prepared some tests for file based on an extended version of mispec. Usually I would split up the tests a bit more but for a rough estimate it should do. If you want to have a look: https://github.com/HHHartmann/nodemcu-firmware/tree/tests/lua_tests @TerryE Terry what you suggest is that someone should stand up and implement tests against the two modules, regardless with what framework (or none at all) and then we will adopt that style and everything is ok? |
@marcelstoer @HHHartmann, I've been making progress on porting the Lua Test Suite onto ESP NodeMCU. See for example my gist Rough cut coroutine based provisioning system. I am falling in love with coroutines. Just see in the gist how they pretty much entirely remove all of the callback crap from your application logic. What I am doing is to rsync the LTS on my PC to an Apache2 directory. The sync script will pull down any updated LFS images and a separate init.lua script cycles though these. It executes really fast. I have a bunch of technical issues that I need to bounce off you guys relating to this suite, but this isn't the issue to have this discussion on. So should I raise this as a separate LUA53 tagged issue? PS. Health warning. These gist scripts run on Lua 5.3 so I've been using some of the nice new 5.3 features, but it should be easy to back port them to Lua 5.1 for anyone that's interested. |
@TerryE, @nwf , @marcelstoer Terry I would like to see more of your testing environment. Can you show us your init.lua which cycles through the images? What do you do with the outcomes of the tests? In my opinion test writing and execution has to be as simple as possible. This is because developers tend to see it as a separate burdon to write and execute them. So every extra learning that is needed or any complicated whatever will keep them from writig them. |
In general, I think I'm OK with something like Fundamentally, though, I think we need something like
|
I just started implementing the tests for mispec as it was the only one I was aware of at that time. As for testing net and tls. Could it be possible to configure the NodeMCU as AP and station (I know you can)? But I have no experience with connecting it to itself. Sure would not make the tests any easier as they would have to handle both sides simultaneously. But maybe coroutines cold help here sufficiently |
The broader problem with Besides, if we want to automate anything, we're going to need to parse the stream sent over the UART, so we may as well just bite that bullet now. I've written the beginnings of a test program that just sends many files to the device and then runs the last one with So, ultimately, as I've said before, I think we should...
|
That sounds good, Maybe we can combine it with Terrys LFS image generation. We should use LFS because else we will hit memory constraints too early.
Agree
Also a good idea. gambiarra supports replacing the output generation, so chnaging it to TAP should be no problem (if we use it)
👍
Maybe we can have one device set up as counterpoint for these modules and not change it unless needed for new/changed tests. It could be steered by REST requests from the other device to act as station/AP/tls or be a counterpart for GPIO tests. So orchestration from hostside would not be needed. (or not that much)
That would be to only flash to one device unless required otherwise. We should have as little change and a stable version for this 2. device. Usually no changes would be needed ot just Lua updates. |
Currently I am exploring gambiarra as a test base. If you are interested have another look at PR #2984 |
All my work is available in https://github.com/nwf/nodemcu-firmware/tree/dev-active/tests (but warning, that branch gets frequently I don't anticipate any issues scaling my expect-based system to handling two devices, setting up an AP and STA configuration, and doing cross-device connectivity, but I have not had time to do it yet. |
seeing the discussion in #2984, could we have an agreement to use gambiarra as base for out on device tests and depricate mispec? |
I am happy with this subject to the caveat that Lua core tests will continue to be based on the Lua test suite. It would be a huge effort to port these. |
I think leaving the Lua core tests alone is fine, and I think I can be happy with gambiarra. |
Since we have a test system (NTest) now and @nwf is on tzhe way of hardware components test and using the new GitHub Actions is on the way the next step would be to automatically run tests on Nathaniels test board in the course of CI builds. Doing this seems to be not too hard since GitHub allows self hosted runners for actions now. As I read it only the runner has to be installed and then the needed steps can be defined in the .yml file. The only caveat is that it is not recommended for public repositories due to security implications. See https://docs.github.com/en/free-pro-team@latest/actions/hosting-your-own-runners |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
It would be extremely helpful to have a single Lua script that anyone could run to test hardware-independent modules.
Whenever we cut a release we do so w/o having done any structured and reproducible testing. I understand and accept that it's difficult to do serious (automated) testing for sensor/actor modules because it requires the respective hardware to be installed. However, it'd be fairly straightforward to test all other modules at least partially e.g. WiFi (basic stuff), timer, net/tls, HTTP, sJSON, SNTP, perf, MQTT (against public broker), file, cron, bit etc.
This is related to #516 (i.e. a light version of it).
The text was updated successfully, but these errors were encountered: