-
Notifications
You must be signed in to change notification settings - Fork 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
Rewrites the Mocking section: introduces Mox #2338
Conversation
There seems to be a fair amount of confusion surrounding mocks in Elixir. You CAN use mocks in Elixir, and although there are some considerations for asynchronous execution, the mechanics and preparation are not vastly different than other languages, so I wanted to set the record straight and provide a walk-through that explains a bit of the philosophy so we can understand and use the Mox library.
Thanks for the contribution @fireproofsocks! This is a tricky change. Mox is not an official Elixir core library so traditionally we do not reference those in the lessons themselves. We could link to a lesson on Mox, but I don’t think the basic lesson is the place to introduce this library. We also do not link out to anywhere other than official docs, so the link to Plataformatec needs to go. In my 5 or so years of Elixir I still haven’t needed a mock and I’m not sure we want to suggest that approach so early in the lessons when in fact, it would likely only confuse people’s understanding of testing in FP. I think we need to discuss this with the larger @elixirschool/developers group before considering a merge. |
The link to Platformatec was already in the docs -- that's not something I added. So if it "needs to go", you should remove it from the existing docs. Secondly, that article is literally one of the only articles about this topic and it is authored by José himself, so I would think that would make its inclusion viable. The same justification I think applies to Mox itself (also authored by José). Because Mox handles all the subtler issues (primarily those of asynchronous execution) and covering that in a "package-neutral" way would require an entire chapter of explanation on macros and code reflection, IMO it makes sense to put weight behind the elegant solution that Elixir's author devised. The testing of certain execution paths is only possible with mocks (or with some variant of the "dependency-injection" method outlined), so it's a valid topic for any serious discussion on testing. The thing that prompted me to open this PR was what I felt was misinformation re mocks being "highly discouraged": that is not the case. After many discussions in and out of the forums, my take on this is that the misunderstanding has arisen from the strange Ruby-esque (?) distinction about mocks as a verb vs. mocks as a noun and the general disinclination to achieve 100% test coverage (or close to it). In other words, some of the smelly bizzarro monkey-patching "mocks" favored by Ruby/Python/et al may be highly discouraged (and perhaps with good reason), using mocks to fully test your code, however, is absolutely a valuable tool. If you still don't feel that this is an appropriate PR, I would be happy to rewrite my notes as a blog post on Medium or somewhere, but I would rather not re-invent the wheel when THIS site is a much better reference for the topic. At a minimum, please consider rephrasing the section on mocks so it doesn't turn people off to them -- I could put in a separate PR that more or less truncates the entire section (or perhaps, moves it to a separate section altogether). PS Did we meet at an Elixir meet in Denver? |
Thanks for raising this discussion @fireproofsocks! The topic of mocking in Elixir is definitely an interesting one and a lot of misunderstanding surrounds it, in my opinion due to the "noun vs. verb" distinction. I think that the current lesson's statement:
is meant to refer to mocking as a verb. Instead, the best practice is:
And I think this approach is what your PR outlines in the lead-up to the Mox content. I think this lesson could in fact use some updating along the lines of the first part (pre-Mox) of your proposed changes. In my opinion, the content you included more or less outlines and gives specific examples of what we currently suggest in the lesson:
Although I think if we are going to expand on this topic with examples and more detailed explanation, we should include the whys and hows of using behaviours in any mock implementations. On the topic of Mox however--Elixir School currently aims to provide lessons on Elixir core library offerings only. It's my understanding that we want to avoid putting out opinions on non-core library offerings at this time. While Mox is the go-to mock library for Elixir in my personal opinion and professional experience, it is also the case that there is "more than one way to peel the orange" of mocks in Elixir tests, as this recent Twitter convo once again illustrates. How would you feel about:
|
Ah, that should not have been in there so I can review and remove it, sometimes these things slip by. We have tried really hard to avoid linking to anything but official Elixir documentation so as not to show a preference for one company / consultancy / library. I've always felt that while this may make a few things harder, it allows us to avoid a lot of unpleasantries.
I fully understand but José runs a for-profit Elixir consultancy. Many other people who've contributed to Elixir School do as well but they have had to forego free links to their business. I've avoided linking to employer blogs even though they've allowed me to dedicate a % of my paid time to Elixir open source. José is always welcome to author blog posts here too 😀 Maybe this is a good opportunity for someone with less name recognition to get an opportunity to share some of their lessons.
Mocking and DI are two different things to me and I think it's worth keeping them separate. That may require expanding on this article to better articulate these approaches.
It may not always be the case today but the vast majority of people coming to Elixir have come from a Ruby background which is why this section reads like it does. I still personally don't think mocking is as critical as people in the Elixir space make it out to be, defining know stubs is easy and easy to reason about. That all said, I'm all for including more content but I don't believe this Basic Testing lesson is the place for Mox.
@SophieDeBenedetto / @fireproofsocks I think a blog post would be great but even better why don't we add a Mox lesson under Specifics or Libraries (aside: we should figure out a way to merge these sections maybe?)? My thinking behind this is:
You may have met Sophie or Michael, I unfortunately sustained a serious back injury a few weeks prior and was stuck in CA waiting for clearance to fly again so I missed out. I am however based in Denver, should you ever be in these neck of the woods reach out and we'll grab some coffee 🎉 @SophieDeBenedetto / @fireproofsocks likely a conversation that involves others from the org but what about considering an additional Testing section in the Advanced category? Allowing this lesson to touch on how to do the basic testing and principles with another lesson that covers more advanced techniques like DI, mocking with Mox, and property testing with the latter two also linking our to their dedicated articles. You'd also be introduced to these topics after you've learned more about modules and asynchronous work. Thoughts? |
I want to make sure to address this too: @fireproofsocks please don't think we're pushing back because we don't want your contributions 😰 We love when passionate people such as yourself are willing to share what you know with the greater community. It's not everyday we get to engage in conversations about the content with other passionate folks new to the org. You bring a fresh set eyes to things. 😁 These additions are great I just want to make sure we find the place for them in the content. We really hope you'll continue to share your ideas with us, we're always looking for new contributors for Elixir School and the larger https://github.com/beam-community org. |
Re item 1: unfortunately I don't think I'd be able to shed any light on the distinction between mocking as a noun vs. as a verb because I found the article on the subject to be nearly unintelligible (!). That may sound harsh, but based on conversations with and posts by other developers, I think my confusion was representative. Perhaps my inability to comprehend this distinction stems from my background in languages which never relied on the tortured constructions that seem to be the status quo in Ruby and Python testing where dependency injection et al is rare (but that's just my guess). In any case, I don't think it's useful to harp on the distinction. Rather it would be far more important IMO to demonstrate through example how to properly handle testing code where simulated responses need to be given. Although the first part of the code I shared I found to be a valuable entry point into how to construct code to allow for better testing, the intermittent problems that arose from its use during asynchronous test execution and from ad-hoc functions not constrained by contracts were as subtle as they were difficult to identify and solve. In other words, omitting a library like Mox which solves these problems would require a much longer conversation on the minutiae surrounding test execution and contracts which, although interesting, may not be as beneficial as just demonstrating a valid pattern. Re item 2: If your documentation has as its goal "purity" and not necessarily "practicality" (i.e. thou shalt not reference anything but the core library), then would it be acceptable to reference the blog post in the docs? Again, the primary problem requiring a solution here is the dearth of accurate/practical information about mocks/testing in Elixir -- the exact placement of any remedy is secondary to me, I just want to see improvements somewhere. |
@doomspork / @SophieDeBenedetto : if we want to tackle this as a blog post, I think it would make a lot of sense to pair up Mox with ExCoveralls as part of drilling down to get 100% code coverage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would only suggest two things:
a) make it so a new phrase is in it's own line.
b) move this into it's own lesson, and reference it in testing.
The second part is because we don't want to cram more stuff into the existing lessons, it makes it harder for translators to follow a change.
Re: conversation above, I believe we should avoid doing blog posts when there is stuff that can be updated and be put to good use later. Write a blog post when it's about an opinion, a TIL, a review, but everything else should be lessons. |
@doomspork @fireproofsocks I love the idea of putting this lesson under @doomspork could you elaborate a bit more on what clarifications/updates you'd like to see in this lesson on the topic of mocks though? |
@SophieDeBenedetto are you asking about my comment "what about considering an additional Testing section in the Advanced category"? If so I guess I am thinking we clean up the Basic Testing lesson to stay basic and expand on the more advanced topics (DI, mox, bypass, property testing) in an Advanced Lesson. |
RE: linking to other blog posts, I agree, we shouldn't do it. @fireproofsocks you should remove mentions of Jose and his blog post and the lesson should be solid :) |
… before and after code blocks, corrects mention of 'expect' as a function (it is not a macro), combs through for better readability
Ok, I made changes per the suggestions and gave the verbiage a comb-through. Please let me know if anything else needs attention. |
Bump? Is something else required? Thanks! |
Hi @fireproofsocks! Sorry this seems to have slipped through the cracks, thank you for the ping 🔔
I know you mentioned that you didn't feel super confident addressing the first point by updating the existing Testing lesson. I'd be happy to open a PR to that effect and you can take over basically just taking the new Mox content you added here and PR'ing it as a separate, standalone lesson either under the Let me know what you think! 🌞 🍪 🧁 |
That sounds fine -- as I mentioned, the overall organizational strategy of the documentation isn't something I care overly much about, my priority is sharing accurate information. If you can open a PR to that effect with these changes going into the proper place, that would be great. I'm not sure whether I expressed any doubts as to updating the current lesson, but that was not my intent. My priority continues to be to nix the misleading/incorrect statement that Elixir discourages mocks -- I've encountered too many developers who pointed to this page as their sole justification as to why they didn't bother writing tests for things that required mocks. Can we make a smaller PR against this page that corrects the problematic statement and links to the |
@fireproofsocks I think that would be a great approach (smaller update, link to lesson). A lesson on Mox will allow us to expand on how to use it more in-depth. Very exciting content 🎉 |
Great. I propose that we do this:
Sound good? |
Sounds good to me--I'd be happy to open a PR moving your Mox lesson to a new location. In that same PR I will update the existing test lesson to clarify the mocking recommendations and link to the new lesson. Thanks again for you contributions @fireproofsocks 🔥 🧦 😄 |
Closing in favor of new PR here #2343 |
There seems to be a fair amount of confusion surrounding mocks in Elixir. You CAN use mocks in Elixir, and although there are some considerations for asynchronous execution, the mechanics and preparation are not vastly different than other languages, so I wanted to set the record straight and provide a walk-through that explains a bit of the philosophy so we can understand and use the Mox library.