Testing in Context with Lachlan Miller
Today’s special guest on Enjoy the Vue is Lachlan Miller, a full-stack software developer who is passionate about open-source, test-driven development, and mentoring. You may know him for his involvement in the Vue.js community and his work on Vue Test Utils. You may have even read the book he wrote about it, Design Patterns for Vue.js, which arms developers with the tools, patterns, and concepts they need to build complex, scalable, and testable applications. In part one of our conversation with Lachlan, we cover testing in all its complexity, from viewing it as everyone’s responsibility, not just the developer’s, to deciding on which tests to use, deciding where your priorities lie, and how you can put in 20 percent effort for 80 percent output. Tune in today!
Key Points From This Episode:
- An introduction to today’s special guest, Lachlan Miller.
- Given the hypothetical opportunity to test only one thing about an app, Ben, Tessa, and Lachlan weigh in.
- Lachlan suggests doing a screenshot test of the application using a tool like Percy.
- Hear about the distinction between screenshot tests and snapshot tests.
- The panel reflects on whether developers should test their own code or have a QA team assume that responsibility.
- The spectrum of testing, from end-to-end to the more fine-grained and individual unit tests.
- Learn about Testing Library Vue, a recently popular alternative to a library like Cypress.
- The benefits of having accessibility testing built in, for both developers and users.
- How to decide where your priorities lie based on which tests you focus on.
- Lachlan explains how he uses unit tests to drive development while end-to-end tests function more like a quality tool.
- How you can use the Pareto effect to make these decisions as a developer: how can you put in 20 percent effort for 80 percent output?
- Some of the panel’s favorite resources and methodologies for writing Vuex tests.
- “If we think of testing as not just the developer's responsibility but everyone’s responsibility, it's about quality assurance and confidence. Everyone in the organization wants to be involved in the quality of their product, which is why visual tests can be very useful.” — @Lachlan19900 [0:05:31]
- “If you are interested in the more end-to-end tests but you don't want to spin up a full browser, I would definitely recommend checking out Testing Library Vue, which is running on top of Vue Test Utils.” — @Lachlan19900 [0:15:45]
- “The most important thing is you are confident in your app. Everyone's going to have a different version of confidence, but if you have a feature and if it breaks and it would cause a bad thing to happen to your business, you probably want to have a test around that.” — @Lachlan19900 [0:19:56]
- “A good rule of thumb is the more you can test your application or your apps in a production-like manner, it's going to be better.” — @Lachlan19900 [0:30:36]
EPISODE 60 (PART 1)
[00:00:09] A: Hey, everybody, and welcome to Enjoy the Vue. I'm Alex. Today, on our panel we have Tessa.
[00:00:16] T: Hi.
[00:00:17] A: And Ben.
[00:00:19] B: Hello, hello.
[00:00:21] A: Our special guest for this episode is Lachlan Miller.
[00:00:24] LM: Hi, everyone.
[00:00:27] A: Lachlan, would you like to introduce yourself?
[00:00:30] LM: Sure thing. Thanks, Alex. Hi, everyone. I'm Lachlan. I maintain Vue Test Utils, so you might have seen me around there in my free time. In my day job, I work at Cypress, so I'm working on testing tooling by both day and night. I'm really excited to be here with you guys.
[00:00:46] A: Well, we're excited to have you here too. So, first question, I'm going to ask Ben and Tessa and see what they think. If you could test one part of your app, what would you focus on testing?
[00:01:04] B: If we could only test one part?
[00:01:07] A: Yeah, one part. That's it. That's all you got. You can do one thing and test one thing. What do you want to test?
[00:01:15] T: I just remembered that Chris has that thing where he's like, “Test the checkout process so they can give you money.” That's not what I’d test. But it just occurred to me. That was the thing.
[00:01:25] A: Yeah, I think Chris has two things. It's always, it's the thing that allows them to give you money and your login. If you don't test those two things, you don't have an application.
[00:01:34] B: Yup, you don’t have an app.
[00:01:36] T: Yeah. But if he could only choose one, Alex.
[00:01:39] A: I’d probably choose login.
[00:01:41] T: Nice.
[00:01:42] A: Because we would notice that we weren't making money pretty quickly.
[00:01:47] B: Okay, that's fair. That's a fair argument. Yeah, my first instinct was to save money, like, make sure that they can pay us.
[00:01:54] T: Yeah, then I can spend the money on the engineers to make the login work.
[00:01:58] A: Well, there you go.
[00:02:00] LM: I was going to say the same thing, actually. I threw together a little website to sell a book a while ago and I had one end-to-end one test, which was just logging in and purchasing the product, because that's the most important thing, right? As long as they can log in and give you money, as you said, that's pretty important part of the app, right?
[00:02:18] T: That's true.
[00:02:19] A: I would say so.
[00:02:21] T: I think for me; my main interest and focus has been on like the user interface itself. So, for me the things, the frequent headaches that I have is if I need to change something in a component, and it's being used in a bunch of different ways, in a bunch of different places, or I don't know where how it's being used, or if it's resizable. So, I think, for me, I would probably choose to test like the – if I had some kind of testing around the appearance and use cases of the component, like maybe a storybook or something. I don't think storybook itself has testing, but something along those lines, where you can see all the components and run through the different use cases and make sure you didn't break anything whenever you change the components.
[00:03:09] LM: Yeah, there's a tool called Percy for screenshot testing, visual testing. That sort of thing can be good or very easy to implement, but you get a lot of coverage. So yeah, maybe I consider a screenshot test of the entire kind of main area of my application, just to know that that's all working correctly.
[00:03:28] B: Yeah, I've heard a lot about Percy, but haven't used it myself.
[00:03:31] T: One question that I would have around something like Percy is, if it's different to other screenshot testing utilities, which I feel like, basically, the way it works is it gives you a text output of the markup of your component, which sometimes, depending on your testing setup, it may not highlight the differences. If, say, the auto generated hash for your Vue components changes whenever you rerun the tests, then developers might ignore the screenshot changes. Also, I don't think it really helps to account for if, for example, you made an input 100 percent width, instead of, like, 20 pixels. Does that not work in some places but works in others kind of thing?
[00:04:11] LM: Sure, you mean like a snapshot test versus an actual screenshot or something like that?
[00:04:18] T: Yes, that's probably a good distinction. I was thinking snapshot and not screenshot.
[00:04:25] LM: Oh, sure. I mean, yeah, like, snapshots can be pretty good as well, right? Like a lot of coverage for very little time spent. I think you do have to be somewhat cautious because it's very easy to get complacent and just update the snapshot without really scrutinizing it. But one of the nice things about a tool like Percy is it will actually show you the before and after screenshot and, a lot of the time, you have to actually improve the changes for your pull request to be passing on CI. So, it really does block your CI from passing until you visually inspect it and you can actually use a different person in the organization, maybe the product owner can be involved in the process then.
That's pretty valuable, right? Because that way you have different teams with different sort of priorities all being involved in the quality assurance process, which I think can be pretty valuable.
[00:05:15] B: That's an excellent point. Because I know having worked with snapshot testing in the past, like, I have definitely been guilty of like, “Yeah, I think that looks right, commit.” I'm moving on. I have something else to do. Because it is hard, especially looking at the snapshot, just staring at a wall of text, being like, “Yeah.”
[00:05:30] LM: Yeah. I mean, if we think of testing as not just the developer's responsibility, but everyone’s responsibility, it's about quality assurance and confidence. I think everyone in the organization probably wants to be involved in the quality of their product, which is why visual tests like screenshot can be very useful. Anyone can understand it, it's very easy to interpret.
[00:05:53] A: Yeah, we definitely ran into an issue at work the other day where we changed some selector ever so slightly, and a bunch of buttons that used to be green suddenly turned yellow. So, that would have been handy to have.
[00:06:11] LM: That's pretty big deal, right? Like the color can really change, like, what the user thinks a button does, or even make them into something erroneously. So, it seems like a small thing, but it can really blow up from that.
[00:06:24] T: So, not knowing anything about Percy, I was wondering if you could talk a little bit more about for example, does it do visual diffing?
[00:06:31] LM: Percy?
[00:06:33] T: Yeah. Or is it more like you look at the snapshots and examine it manually yourself to see what's different?
[00:06:38] LM: I think examine it manually, generally, I haven't used it a ton. I had it at my companies where I've worked. But it's usually been someone else's responsibility, generally a QA position, which I think is great to have a different person from the actual person writing the code to review it. Because it's easy to miss things in your own code.
But yeah, I think the idea is it just shows two screenshots and you can see, okay, is this change valid or not? And by being able to see the previous state and the new state, it's usually pretty obvious.
[00:07:10] T: Nice. That makes sense. Yeah, that's pretty cool. I think I read that on the design side of things, there have been a lot of changes where you can like version control your visual designs, and also like, track diffs across them. So, I thought, if a visual testing tool had that, that would be pretty neat, as well.
But you bring up another good point, which is I think that there is – maybe it's a lopsided debate. I don't know that much about it. But I do think that there seems to be some ambivalence over whether someone should test or QA their own code, or if somebody else should do it. So, what are everybody's thoughts there?
[00:07:48] A: So, at my company, we definitely have a QA team as well as developers writing tests. For a long time, they were very distinct and separate and we're now doing a lot more overlapping, where we're saying, “Hey, QA, if there's something that you – every time that we make a change, you go do, just tell us what that is and we'll write that test so that you don't have to do it.” We're working more with QA, I guess, as a developer, and trying to write more end-to-end tests using Cypress or testing the components individually. So, yeah, that's how we handle it. Ben?
[00:08:33] B: From my end, yeah, it's definitely a tricky subject because, a lot of times, you don't want developers to just write code and just toss it to QA to test because then you do create a lot of basically time sort of back and forth in that case. I do think developers should be responsible for trying to keep the quality of what they're doing high. But I think part of the problem is the encapsulation of what we often care about as developers when we're building.
When we're trying to fix a specific problem, we do try our best to account for things and we will try to write test accordingly, but I think sometimes the mindset in which sometimes you have to think about the end user and what they might do, that is almost a different mindset in itself. So, I do think it's important to have someone whose responsibility it is to do that check. So, someone, as Alex said, having some sort of QA team to really facilitate that sort of thinking, whether it's sort of penetration testing or just figuring out ways to intentionally break it, because I think developers were focused on fixing. I think it is important to have that sort of separation of concerns.
Again, to Lachlan’s point, it’s not that everyone shouldn't care about testing. You should. It's just like someone should in an organization have a clear ownership and responsibility over that.
[00:09:36] LM: Yeah, I agree. Obviously, developers need to be testing their code as much as they can, both manually and with tests, but I think there's a lot of value in having a third party, whether it's like another developer, QA, product owner, someone else actually going over your change and making sure they're happy with it. Because obviously, you've tested yourself and you think you've everything you can but there's always going to things you miss or little use cases you're not aware of. So, yeah. I think there's a lot of value in having not only automated tests, but also having manual QA to an extent.
Cypress and stuff like that is pretty good. You can get a lot of mileage. But I think the role of QA is a little bit different. Automated tests are good for known use cases, but there's always going to be these unknown use cases and having someone to do those. The value of something like Cypress is, it frees up their time to spend on these other more difficult things like exploring new use cases, exploring new features, that sort of thing.
[00:10:35] B: I love that. Yes. What do you think, Tessa?
[00:10:40] T: I don't really have any particularly strong opinions, or particularly in-depth experience around testing or QA. So, one team that I worked on, we had a test automation team. I never understood what the team responsibilities were. I knew that they were not writing tests, and they were not QA. What they were, I'm still not sure. But I did a lot of like Selenium stuff there. I don't remember any kind of like visual QA process.
Another team I was on, we had a QA project manager, and then like a large overseas QA team. So, I think, both with that team, and then their successor, which was a single QA engineer, we would work together to write out these test plans and then the QA team or engineer would go through the test plans and let us know what they found, like if the test passed or didn't pass. And then another team that I was on, it was a fairly small team, and the policy there was because we are small and don't have QA, everybody is supposed to QA their own feature. So, those are the three different types of experiences that I've had with testing and QA.
[00:11:56] LM: It sounds like we're all talking about testing in the end-to-end sense quite a bit where you test the feature, something you can see. But then we have the opposite end of the spectrum where you have like, these very fine-grained unit tests for very specific functionality or sometimes you're implementing a feature that doesn't have a UI yet. So, there's definitely limitations on what you can test both visually and manually.
On the opposite end of the spectrum, there is something like Cypress, which is very end-to-end. You have test utilities, the very dedicated library that does one specific thing. I'm interested in your experience with like doing the different ends kinds of tests, like the really big end-to-end tests and the more fine-grained tests. Which ones do you find or you guys find more valuable? Which ones do you find easier to write? What are your thoughts around this topic? Because I think it's quite an interesting one.
[00:12:48] A: We definitely write end-to-end tests at work as well as unit tests, using Vue Test Utils. We, for a very long time, we’re pinned at an older beta version of Vue Test Utils. So, there were definitely some tests that we wrote that we then tried to upgrade and something had changed. So, we're still sort of, we've upgraded and we're now back into the regular flow of updates, but we're still finding things where it's like, “Oh, why is this not working?” But it's been good, because a lot of the stuff, it makes us think about how to break things up better. If you can individually unit test a thing, that probably means that you have made it small enough.
If you are trying to unit test something and you have to write 8,000 lines of unit tests to test this one component, it might be doing too much, and you you may want to think about breaking it up into smaller pieces. It's a good indicator of complexity. But at the same time, the end-to-end tests are great, because we can tell when the development server goes down before the development team knows that the development server has gone down, because we're running end-to-end tests and it'll just suddenly stop working completely. So, it's a great indicator for us.
[00:14:21] LM: Yeah, and that's exactly what you want. You want to know if something's broken immediately, certainly before it gets to production, and, if possible, before it even gets merged into trunk or develop. So, yeah, that's a definitely interesting perspective on measuring complexity with the kind of tests that you write.
There is another library, which has become more popular recently called Testing Library. I'm not sure if you guys are familiar with it, but by Kent C. Dodds, kind of a figurehead in the React testing community. The State of JS survey actually came out yesterday, I think, or the day before, and they had the testing section. Testing Library had an average rating of 97. I'm not sure how they measure that, but I'm guessing the scale is 0 to 100 and 97 being a high level of satisfaction. I think Cypress was at 94, so those are definitely two of the most popular testing libraries.
The reason I mentioned this is Testing Library is sort of in between the Test Utils of the world and the Cypresses of the world. It really focuses on user behavior, but it's still running in a terminal work environment, so you don't have the full UI or a real browser. But the tradeoff is the tests are easier to write, apparently. I'm not convinced on that. But they’re definitely faster to run and set up. It's an interesting middle ground. I'm interested to see how that turns out.
We actually have Vue integration for Testing Library now as well, for both Vue 2 and Vue 3. So, if you are interested in the more end-to-end tests, but you don't want to spin up a full browser, I would definitely recommend checking out Testing Library Vue, which is running on top of Vue Test Utils. So, you get all of those features, plus the extra part of testing library as well.
[00:16:03] A: I will have to look into this.
[00:16:05] T: Nice.
[00:16:06] A: I have some side projects where I'm like, I really need to integrate some tests into this.
[00:16:12] LM: One of the problems it solves is, I guess, if you use Vue Test Utils before you'll know you have to often wait for next tick for the DOM to update, which is pretty – it's not what you want to think about when you're writing tests. Testing Library has obviously learned from the past experience of libraries like Enzyme that didn't really support these sorts of things very well, and has a lot of good utilities for waiting for the DOM to update. So, you can have like a wait for element and it will wait until your element appears, as opposed to something like Vue Test Utils, where you have to say, next tick to make sure the DOM has updated so you can assert your element is present.
I thought that was a pretty nice feature. I've been using it for a few projects recently, and feels pretty good. So, definitely worth checking out.
[00:16:55] T: Yeah, I think I remember hearing that another feature that stands out about Testing Library is that it has accessibility testing built in. So, from the get go, you're testing to make sure that your components have some modicum of accessibility features, which I think is pretty nice.
[00:17:16] LM: It's very strong on the philosophy, so they have recommended ways to do everything. If you're one of the people that just likes to have a way of doing things, and that's how it's done, you might find that useful. Test Utils has no opinions at all. It's a very small, simple library. But that can lead you to write unideal tests, depending on your ideals. But I guess the Testing Library team have decided how they like to write tests. And if you agree with that philosophy, it's pretty nice because they even have a list of selectors you can use in recommended order.
For example, as Tessa mentioned, they will recommend you use the accessibility selectors first. So, if you want to click on a button, you might find it using the role attribute, which would make sure your application is not only usable by a regular user but also by someone on a screen reader or with visual impairment, which is pretty cool, right?
It's something we often forget about as developers, so being able to get accessibility testing for free or being able to be exposed to it more is definitely something I like about the library.
My impression, looking from the outside in, is that the Testing Library philosophy seems to be quite different from the Cypress testing philosophy, which also seems to be quite strong. I'm basing that entirely off of like, [inaudible 0:18:41] being very outspoken about what things he thinks should be and should not be tested. And then I saw GLib from Cypress once talk about like an inverted testing hierarchy or something. So, I'm curious what people's thoughts are on that? Like, how do you decide where your priorities lie in terms of which tests should you focus the most of your time and energy on?
[00:19:05] LM: Sure, that's a really good one. For sure. On the idea of like philosophy, as you were saying, some Test Utils is good, because it has lots of different things for different use cases. For example, it has a shallow mount feature, if you want to focus on unit tests, has a mount feature if you want to render the entire component. Things like Testing Library and Cypress will be more opinionated, they'll just be like, you can only mount, you cannot shell them out because we want to make our test as much like the user sees it in a browser.
But as it comes to deciding what to test, I think there was a time where I’d try and get 100 percent test coverage. I wanted to have every line with the coverage and make sure everything was tested. But I ended up with what are duplicated tests and also end up spending quite a lot of time for not a huge benefit. So, I think that the most important thing is you're confident in your app. Everyone's going to have a different version of confidence, but I would say, if you have a feature, and if it breaks, and it would cause a bad thing to happen to your business, you probably want to have a test around that. I would just think about it in terms of my confidence and how I would feel if my users were exposed to this breakage. So, that's probably how I try and think nowadays, from a user perspective as opposed from a developer perspective.
[00:20:26] A: Yeah, I'm thinking about just, sort of, I know that I've been taught the hierarchy of testing, where it's you have very few end-to-end tests and then you have more integration tests and then you have a lot of unit tests.
[00:20:44] LM: Do you agree? What do you think?
[00:20:46] A: I don't know. I think it depends on what the application is, right? I think that unit testing components is good. If you're like, “Okay, I'm going to put in this information and I'm expecting it to, like, if I click a button inside of it, that it's going to pop this information back out.” That's a very atomic test. You don't need to instantiate the entire application to test that one thing. For that, unit tests are fantastic. But at the same time, if we're talking about testing Vue and testing user interfaces, then yeah, you're never going to necessarily interact as a user with that component in that way.
I think leaning more towards end-to-end tests is a better thing, especially when we're talking about interfaces for users. Similarly, if you were doing, if you had an API rather than doing a full end-to-end test, the thing that you should be focusing on with your API, if that's the thing that you're supporting, I would say, doing the integration test where you say, “I'm expecting this API endpoint to have this information. You may not care about how the user interacts with it, but you do care that the data comes in and out correctly.”
I think it really depends on what your focus is. As people who make user interfaces, I would think it's probably better to focus more on how the user interacts with it.
[00:22:19] T: I think I find myself perhaps a little bit biased towards or leaning into this idea that E2E is better or end-to-end is better, just because I think when we describe tests as user stories, I feel like that kind of has a nice parallel with when we think about something like end-to-end testing, where there's an involved list of processes versus like with unit tests. To me, it's a little bit more obscure how to decide what to test. But then on the other hand, I think because they're less brittle, it's hard for me to tell if we end up with this idea of having most tests be unit tests because they're less painful to write and keep updated or because they are serving whatever our ultimate purpose for testing is, if that makes sense.
[00:23:07] LM: Yeah, I agree with that path of least resistance for the point you made. I think a lot of people are big on unit testing because they're so easy to write, like, you just generally install whatever, Test Utils, something like that and it just works. There's not very much setup involved. When you have an end-to-end test, you probably need a server, you probably need a database, you probably need all these different things. There are just a lot of stuff to do.
Obviously, there's value there. But I mean, if you need to make sure you have a good environment to write the test, once you do, it's really easy. But a lot of the time, especially for existing applications that have not been written with testing in mind, it can be really difficult to get end-to-end pipeline setup that's actually reliable. I think that turns people off a lot.
Another interesting way I kind of think about it is, I often use unit tests to drive my development. So, they're a development tool. But the end-to-end tests are much more a quality tool. I think they also serve different purposes as well and both have their place.
[00:24:06] A: I think another thing that end-to-end tests or unit tests are actually really good for is you're also testing the developer interface, right? So, end-to-end tests are, as a user, I expect this thing to happen. I go on a page, it does a thing, it loads this data, blah, blah, blah. With unit tests, it's, as a developer, I expect this component to behave this way when I use it.
It's the mindset of who is using the thing. With unit tests, I may not necessarily be testing the interface. I'm more likely to be testing the developer interface. So, it should give me an error if it's missing this prop. It should be emitting this type of an event, etcetera, etcetera, etcetera.
Then I can be sure that if somebody goes in and goes, actually, we should really rename this event to something else, I have a test that says, “No”. You need to be able to – if somebody just inadvertently goes, “I'm just going to replace all my click events with like double click events.” No, you can't do that. You really need to make sure that it's working correctly. That's sort of the other mindset that I'm into is that you need to be testing the interface that you're trying to talk to basically.
[00:25:31] LM: I like that actually, testing the developer interface. It's kind of like documentation in a way. If you have one very focused unit test, the unit test clicks a button, it's this one thing, that it does, and you know what it does. That can be very useful to a developer, especially if you have a component where it's very complex with many different props.
Something that comes to mind to me is Vuetify. It's probably the most popular component library for Vue. It's huge. There are so many features. But as a result, can be very difficult to know what's going on and what all the features are. So, having good unit tests can kind of document what the components can do, which is a good, another kind of bonus. You get test coverage, and you get documentation at the same time. Well written tests have multiple purposes in that sense.
[00:26:18] B: I think what's tricky when it comes to the what to test question is it often depends on what mindset you're in. So, I talked a little bit about this earlier regarding like the developer mindset. I think a lot of times we fail to understand, like, the fact that it's – feeling productive versus being effective are two very different things and, with testing, I think they conflate very easily, right? Because if you get 100 percent test coverage that might feel very productive. But as we sort of have joked about earlier, it might not be effective for your apps bottom line, if say, you have critical paths that end up failing.
I know that, as developers, to Lachlan’s point, it can be very expensive and we may not even have the, call it the influence to like get the resources we need to set up proper end-to-end testing and etcetera. I usually like to refer to the Pareto effect when I make these decisions. What’s the 20 percent of effort I can do to get 80 percent of output? I try to apply that to a critical path. If you can do that, again, even if you're a developer, you can’t affect the whole stack. But this is where like if you can affect the unit test and find out the most critical unit test that can impact 80 percent of those use cases, and if you keep at it that way, I think that's how you can drive the most impact on your organization, regardless of what level you're at.
[00:27:31] LM: I definitely like the idea of focusing on the 80 percent. Because yeah, if you can get a decent amount of coverage, maybe you're not just testing. But in general, like, it feels like 80 percent can get you most of the way there. The last 20 percent can be a lot of work for diminishing gains, right? So yeah, I think there's a lot of value in being kind of pragmatic there and just seeing what can I do with the given time and resources? What's the most value I can get here?
At least for me, when I have a very limited time, I feel like a few end-to-end tests to just go through everything is the best way to spend my time because at least you know that, as you said, like the basic things are working, you can log in, you can purchase a product. A lot of the time, if your app is not so complicated, that's probably good enough, at least better than nothing, and it can help give you that confidence that at least you are not going into production with a completely broken stack.
[00:28:27] T: I think to switch tracks back to unit testing for a bit, one thing that I always struggle with is testing the Vuex store and mocking out the different parts of the Vuex when I need Vuex stuff in my unit tests for my component. So, I was wondering what everybody's favorite resources when they're writing the Vuex tests are and how to mock all those things out without too much friction?
[00:28:53] B: For me, when it comes to testing things like Vuex, I don't think I've ever written a test to try to mock it out. Because I think this is where I fall a little bit more in the Cypress philosophy of, I really just want to click the button and I want to see the output. I haven't needed or wanted to test it at the level where I want to make sure that mutation is committed and then this thing triggers. Because, I guess, for me, like I've usually gone the sort of minimalist route when it comes to testing. If it doesn't happen at the end user part, regardless of what happened in the middle, it's that kind of declarative imperative programming bit where it's like, I don't really care exactly how it does it. I want to make sure it's at the end result. Now, I know that people need it. But that's just been my experience with how I approached that kind of thing.
[00:29:34] LM: Yeah, I personally don't tend to mock when I can avoid it. So, I'm happy to use a real Vuex store in my tests. I have no problem with that. I have had the experience where I had a very complex action that did a ton of preprocessing on data before it would send it to a server for example. It turned out that ripping that out of the action and writing a unit test was really valuable because there were many, many edge cases and to test if a data transformation is happening, it didn't make a ton of sense to mount this component and dispatch this action.
I have extracted about logic app before. But yeah, in terms of like testing my Vue components and their relationship with Vuex, I think I personally am happy to have a real Vuex store. I know there are people that have massively complicated Vuex stores that for that reason, don't use a full store in their tests, because it's impractical. Apparently, I haven't had that experience. But there are probably massive apps out there that I haven't worked on that have a different sort of backstory.
But yeah, I think a good rule of thumb is the more you can test your application or your apps in a production like manner, it's going to be better. So, if you can avoid mocking something, I think you get a little bit more coverage and probably minimize the amount of tests you need to write.
[00:30:52] B: I mean, I want to push on that a little bit though. Like if your Vuex store is so massive that you can't bring it in, it almost feels like that's a little bit of a code smell. Like how much you're basically relying on Vuex to sort of carry everything.
[00:31:07] LM: So, you think like, maybe extracting some state out of it, and keeping it in a local component or something like that?
[00:31:13] B: Yeah, or just like more modularization around it. Like, I feel like if I were to run tests, it just seems like something could be architected differently, because it's not like they just relied on the Vuex to carry everything around the app, rather than being more intentional, around modular design patterns. I'm hoping that, with Vue 3, people will start to think of state a little bit more differently, not as some sort of like global monolith that Vuex carries everywhere.
[00:31:39] LM: Yeah.
[00:31:40] B: I guess we’ll see.
[00:31:41] T: So then, let's say you are working on one of those apps that uses the store as like this giant container, or vehicle or bus, if you will, to carry state around the whole app. And your store relies on making a lot of external API calls and you need to test a component that uses data from that, how would you go about testing that, whether you mock or don't mock either way?
[00:32:06] A: In our code base, we have a lot of Vuex modules, and that allows us to use the real Vuex module, but we don't need to bring in the entirety of Vuex. We don't have to bring in the entire store. So, when we're writing the test, we have a way of mocking, not mocking, but creating a localized Vuex for that set of tests that has just the module or modules that we need. And then the component will function correctly with that or with without that. We also write unit tests for our Vuex modules as well. Because once again, it's a developer interface and so we are wanting to make sure that we test that when we put in things, we want to make sure that we get back the thing that we're expecting as a developer.
Our mindset is a little bit different and part of that is that we have multiple sort of – we have one giant application, but like there's multiple pages that do completely separate things. You may be using the same data across multiple subpages, but we've chosen to make it so that it's easy for us to test specific things. We've made some extra helpers to say, “Okay, cool. When you want to get data, here is a thing you can use, and it will give you all of your helpers.” So, then we only have to test that the data fetching works once and we don't have to go and test that the data fetching works in every single module, we can go, “Hey, this thing works, so it'll work here.”
[00:33:58] LM: That sounds like a pretty reasonable compromise to me. I did have an experience of working on one app where it had many Vuex modules, but they all depended on each other. So, there’s one module called Auth, I think, and it would have all the authentication state, and it was just referenced everywhere. So, if you wanted to create one module, you had to have Auth, and then you had to have this other module. It was this kind of big spiraling complexity where everything was coupled together.
I think that's the kind of problem people have had and that's why they tend to mock out certain things because otherwise you're trying to write a test for something that's completely unrelated and it just gets really difficult. I mean, there are limitations if your app is architected in that manner, which is one of the nice things about unit tests is they tend to reveal these patterns, much better than end-to-end tests do. But yeah, there's certain complexity there that sometimes you can't really work around. But generally, yeah, if you can, as Alex said, keep everything nice and kind of separated, it is possible to create a Vuex store with not the entire Vuex store, just the module you're interested in. And that can be a pretty good kind of place to meet when you're writing your tests.
[END OF EPISODE]
[00:35:05] A: That's it for this week. Thanks for listening, and we hope you Enjoy the Vue.