-
Notifications
You must be signed in to change notification settings - Fork 270
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
Integration with AutoTools (and other test frameworks)? #137
Comments
I'm not terribly familiar with Automake. What is it about the way CMock builds things that doesn't integrate well with it already? Is it an issue of knowing WHEN to make a mock? |
Hey, thanks for the prompt reply. I really appreciate your taking the time to review and respond to these massive walls of text. :) Yes, the WHEN is a big part of it. There are two other parts.
The TLDR is that granular mocking is currently impossible without a massive explosion of header files, and since generated sources need their dependencies managed manually in Automake, maintenance gets out of hand rather quickly. Otherwise you risk name conflicts and outright inability to mock interactions between functions in the same interface. Putting a tiny bit more control in the user's hands for fine-tuning the compilation/linking process seems like an overall win no matter what pipeline you're using. I'm not an autotools guru, but I'll share what I think I know about it if you care to read it for a more informed decision. :) A detailed look at the problemTake the following abridged
The Let's take it line by line.
We would repeat this for every test. To integrate CMock into this, we might need to add quite a bit to all of those lines. We need to build Now, we have a few options. The one I proved out was the surgical-strike, which mocks only what is absolutely necessary for a test. Let's say I'm testing a function from my library called
Yeesh, that got out of hand quickly. Here we have a new Automake concept: This gets pretty cumbersome when we want to mock more individual functions. Now let's expand this with a more problematic example. Let's say we have a Let's say that our generated, mocked implementations had a wrapper prefix to avoid name conflicts, and let's also suppose they are generated and built in a separate Automake file into their own libraries so our Automake test rules don't explode in size. Now the above could become this:
Here we've replaced the program Now we have everything mocked in We still have the same problem with the runners. It's not ideal, but at least those are 1:1 relationships, and mocking doesn't explode in complexity. We've technically just kicked the can down the road with mocks, but consolidating them in larger chunks elsewhere makes building/cleaning/dependency-tracking much simpler. Just imagine if we want to mock other system calls, or other libraries that are depended on, or in this case mock the same library we're testing! As I mentioned in the issue statement, there are other clever alternatives to This might seem quite bureaucratic, but it automates source distribution in a way that ensures you don't accidentally distribute things you don't mean to, nor leave a mess behind you when building, installing, and uninstalling. All at the cost of developers needing to be more explicit. It's partly a philosophical thing, but it's also for portability reasons. Despite being very GNU, Automake ensures the built Makefile syntax doesn't rely on GNU make extensions, which is why adding "clever" Makefile segments to Automake is frowned upon. Autogen exists to remedy this, but that's somewhat out of scope here. If you decided to read that explanation, I commend you and hope it helped you understand my struggle a bit better. :) |
Hi there. CMock is wonderful. Thanks for making it!
I've been evaluating a number of mocking/testing frameworks for an application-layer embedded Linux library suite, and so far the CMock API is my favorite. However, we use AutoTools for builds and it doesn't seem to integrate well with the bureaucratic nature of Automake.
I think the problem is that it doesn't quite philosophically align well with Automake since it builds sources in a way that doesn't play nice with Automake's dependency tracking, which in turn makes test drivers less happy. I think this is a necessary evil of how Automake handles distributions, but it would be nice if we could find a way to make integration easier. Maybe we could collaborate to find an elegant pattern and perhaps a way to automate it?
My basic theory is, depending on test strategy, to either conditionally include the generated sources in the real libraries or build mocked sources into their own counterparts of the real libraries. These mocked implementations could then be linked into tests with much less fuss.
Idea A - Facilitate use of the
__wrap_
prefix by allowing the user to specify an arbitrary function prefix. This way the user could use the--wrap
linker flag on GNU compliant linkers. This has a number of advantages in test environments, but would require CMock to have a feature like the one described in #32__wrap_
).It seemed to be given a rain-check due to it being compiler specific, but I believe that having an option for it in the
cmock.yml
could be beneficial in portable use-cases as well. For example, it would enable the user to implement their own stubbing of CMock'd functions even without the--wrap
a laifdef
. It wouldn't be as flexible as--wrap
, but it would be the most portable. A user may even be able to do this stubbing dynamically at runtime, which is another candidate for code generation, but I haven't fleshed that idea out at all.Idea B - There's also weak attributes, which are a little more portable than
--wrap
, and even available in MSVC despite being undocumented. That's another potential solution I've considered exploring since it could provide functionality similar to--wrap
that's slightly more portable. This could also be used in conjunction with the aforementioned prefix stubbing to do one-off mock substitution in test suites. This kind of thing could alternatively be complemented by having some kind of build automation strategy that stubs out individual functions as their own shared libraries that follow some kind of naming convention, which would simulate--wrap
behaviour in a portable way. This idea is kind of vague, but might inspire something more complete.In the case of
--wrap
, testing could be tuned to the function-level. In the case of weak attributes, it could be tuned to the library-level (at least). In the case of stubbing prefixed mocks the result would be similar to weak attributes, though possibly more cumbersome to implement, but also potentially quite powerful for clever users.I agree that portability is a good priority for this framework, but I also think that having the facilities available to make it fit cleanly in build frameworks besides Ceedling is equally important. At the very least, having a clean integration strategy is what I'm looking for. Thoughts?
The text was updated successfully, but these errors were encountered: