DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Unit testing frontend code is (probably) useless
Thomas Hansen
Thomas Hansen

Posted on • Updated on • Originally published at aista.com

Unit testing frontend code is (probably) useless

In Aista we love unit tests. Magic and its satellite projects has 1,000+ unit tests, and some of the satellite projects even has 100% unit test coverage. Statically analysing code using automation is (duh!) kind of important to us. However, unit testing frontend code is quite frankly (probably) ridiculous.

Unit tests are for small units of logic, to automatically ensure that your code is (still) valid as you refactor it, and/or add features to it. If you put logic that requires unit testing into your frontend code, you are probably doing something wrong.

90% of all projects I have worked with in my professional life were enterprise administration tools, and/or customer facing websites, hubs, and registration forms, etc. If you put business logic into these frontend projects, you risk that some smart dude changes his JSON payloads, circumventing your business logic, accessing things that shouldn't be possible to access. You should therefor put your business logic, flows, and validators etc in your backend code. Duplicating some smaller parts of this in your frontend, such as having validators preventing a bogus payload being transmitted to conserve bandwidth is OK - But adding business logic in your frontend to the point where your frontend requires unit testing to verify its logic is still working is either redundant duplication of code to the point where you've effectively created your app "twice", or if you only do it in the frontend quite frankly madness!

There are some exceptions to this such as frontend heavy applications that requires extreme amounts of complex frontend code. An example would be Canva from the real world, that has 95% of its "value proposition" in the frontend, allowing people to create images, presentations, entirely from scratch, almost like a dumbed down version of Photo Shop. BTW, Canva is an awesome tool if you haven't tried it yet. However, most enterprise types of apps should not have any amount of business logic, and or other types of logic in their frontends, requiring unit testing to ensure validity. And if you've got unit tests in such projects, modifying them, and or maintaining them, only becomes harder as a result of your unit tests. And regardless of how many unit tests you have in your project, they will never replace integration testing, and/or QA testing done by human beings.

The first thing I do every time I create a new Angular component, is to delete the "spec" file - Because if I needed it in the first place, somebody should probably slap me in my face ... ;)

Top comments (68)

Collapse
joelbonetr profile image
JoelBonetR • Edited on

There's business logic in the backend and presentation logic in the frontend.

Those are two different types of logic, each on it's own scope and sometimes the line between them is a bit blurry:

A simple example is to show a nice banner to point new users to fulfill it's profiles.

Is it business logic? Well, yes, it's a user journey, convenient for the business purposes. Also it is dependant on the user "state" in the DB that some backend will need to gather.

Is it presentation logic? Well, yes as well, as the way you present the interface to the user differ depending on a flag or whatever approach you took and the data probably propagated to the front-end context state as well.

How do you ensure that this feature keep working in future versions of the software?
Testing.

If you don't have unit tests, you'll need manual testing which is less efficient and more prone to error.

The same happens with the look and feel. I've faced many times an issue that most of us work like that:

  • Tab 1: Acceptance criteria.
  • Tab 2: Design (abstract, figma...)
  • Tab 3: the project. (Not necessarily in this order)

If you're working on a new feature (read "way to present the component to the user depending on certain data" presentation logic) sometimes there's that guy which alters pre-existing styles or structure breaking other feature/s. And it can happen to you and me as well.
Relying on the human memory to avoid this kind of issues is of course not recommended. πŸ˜…

Again, if you didn't had unit tests, you'll need to catch it with manual tests and usually in a later stage (QA/UAT) so the time to "GTD" extends more and more as the complexity of the project grows.

Tests are meant to provide confidence in the code and they do a good job either be in backend or frontend.

Around that:

Magic and its satellite projects has 1,000+ unit tests, and some of the satellite projects even has 100% unit test coverage.

You don't have unit tests coverage but code coverage, and having a 100% is ridiculous even for TDD.
99% of the time, you test public functions/methods, not private ones because there's no sense on it.

Tests (around red/green/refactor lifecycle) are for I/Os, so you cover the API you provide yourself (public functions/methods) and it will break if any implementation detail (private ones) changes on a way it no longer cover the use cases.
If it doesn't break, you'll catch it in a alter stage, add regression tests, fix it and you'll fine to go, this way you ensure the issue will not appear in a future.

Having a 100% coverage is a sign of either overtesting (adding tests for the feeling of seeing more and more green checks when running the suite, without adding a real value to the project/codebase) by not understanding tests properly.

Other kind of tests (UX tests, performance tests...) Don't check on code directly but results and don't increase the % of code coverage.

Collapse
polterguy profile image
Thomas Hansen Author • Edited on

You don't have unit tests coverage but code coverage, and having a 100% is ridiculous even for TDD.

I stand corrected. However, as to 100% code coverage, for most applications this is ridiculous, yes. However, we don't deliver "applications" we deliver libraries, frameworks, and tools for others to build applications on top of. Implying even changing a single property, name, or (sigh!) type of exception thrown given a specific error condition, might in theory break thousands of third party apps, we have no access to, and/or ability to test.

When you write code intended for other developers to integrate into their own code, having 100% is neither abnormal, nor unusual. If you create end user apps, it might be ridiculous, and I don't recommend it - However, we're not delivering "end user apps".

you test public functions/methods, not private ones because there's no sense on it.

If you've got private methods with no possible call path through public methods, you've got garbage code, and you need to apply "SHIFT+DELETE refactoring" ...

As the the rest of your comment, its initial parts, most of it are examples of things that is either literally impossible to test (CSS changes), and/or thing you should not test due to reliance upon networking, or other types of IO (database reliance), etc ...

I'll give you one point though, which is code coverage. The rest of your comment is for the most parts plain wrong ...

Collapse
joelbonetr profile image
JoelBonetR • Edited on

Even you're working on a lib, framework or "tool", you'll have the code logically splitted in this two categories. The public interface (that customers/clients use) is necessarily using the entire private codebase (implementation details) on a way or another, so testing the public one you test indirectly the private one as well.

Testing your private methods/functions directly is still overtesting.

Oh and... Yes, there are ways to test styles applied to any element and to ensure they match the expected. Ypu can also do that for different states (hover, focus...) So you can cover any use case with UI tests.

Unused code simply doesn't fit here and you've different tools to find that: the IDE itself, plugins, tools in the CI pipeline... even a linter can bring an error on that if you configure it properly.

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

The public interface (that customers/clients use) is necessarily using the entire private codebase (implementation details) on a way or another, so testing the public one you test indirectly the private one as well.

Yes, but you said 100% coverage was overkill. I gave you a case where it's not overkill.

Testing your private methods/functions directly is still overtesting.

I never said anything about testing private methods directly, i said, and I quote myself; "we have 100% coverage on some of our components".

Yes, there are ways to test styles applied to any element and to ensure they match the expected

There are also ways to automate usage by creating macros that opens your browser and "pretends" to be a user. They're all for the most parts ridiculous in nature, since their only result is that they give you false negatives as you change your code, and/or add new features to it. If I change the name of a CSS selector to improve code quality for instance, having a "unit test" (notice the double quotes here) break implies my entire foundation for increasing code quality is basically garbage, and my "unit tests" are no longer helping me, but a ball and chain around my neck, prohibiting me from moving forward with speed to improve my app.

Thread Thread
joelbonetr profile image
JoelBonetR • Edited on

This may be a misunderstanding; coverage is measured in lines of code covered directly by tests. You can't get a 100% coverage without testing private methods/functions directly.

Styles testing will fail if you change behaviour, and if you change behaviour it's obvious that you need to update your tests as well.
If your suite fails on selecting an item because you changed some classname maybe what's wrong is the way to select those items πŸ€·πŸ»β€β™€οΈ

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

This may be a misunderstanding; coverage is measured in lines of code covered directly by tests. You can't get a 100% coverage without testing private methods/functions directly

Rubbish. Coverage implies paths of code executed as a consequence of executing your unit tests. Below for instance is a snippet of code

if (someArg) {
   doFoo();
} else {
   doBar();
}
Enter fullscreen mode Exit fullscreen mode

If all my tests for some reasons are entering the above code with someArg always being true, the code inside my else will never execute, and my coverage becomes 50%. If I create a test that passes in false for some reasons, the else will execute and coverage will increase to 100%.

Whether or not the above snippet of code is part of a private method or a public method is irrelevant. You can easily have 100% "coverage" of your code, with thousands of private methods, and never "directly" execute your private methods. If you disagree with the statement in the former sentence, you've got a completely unique definition of "coverage" that I'm certain 99.99999% of all software developers world wide would disagree with you in regards to ...

Edit - Below is coverage of 4 random projects from Magic. As you can see, they've clearly got 100% coverage, even though all projects (obviously) have private methods ...

Unit test coverage

Thread Thread
joelbonetr profile image
JoelBonetR • Edited on

Aha! That's the point I wanted to reach

The problem is, code coverage is a remarkably dumb metric.
In essence, it assumes any test is a good test. It makes no attempt to assess whether you have tested for every scenario.
As a developer, it can be very tempting to assume that good code coverage equates to good testing.

Let’s use a simple example to show what can go wrong.

const product = (a, b) => a * b;

assert product(1, 1) === 1;
Enter fullscreen mode Exit fullscreen mode

Clearly, in the above example, the test achieves 100% code coverage.
However, it isn’t a very good test. For instance, if the operator in product() was changed to divide, the test would still pass! Yet, you have been lulled into a false sense of security because you have 100% code coverage and all your tests pass.

Still, this is better than no tests at all (if the operator changes to sum or subtract it will fail) plus a regression test can simply add an assertion that product(2,3) equals 6 and we should be good from now on.

And that's independent from the context the code resides in either be backend or frontend.
Because following that logic plus the mentioned in the post, if you've a backend that serves a frontend (BFF) why to test the backend in first place then? Simply test the frontend and you'll test the entire backend as well 😁

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

Not only is coverage a good measurement of unit test quality, but it is also the only measure stick we've got. Is it perfect? No. Is your snippet an example of a test where it misses things? Yes. But it's still for all practical concerns the only measurement we've got to (statically) analyse unit test "quality". You still need to bring your brain to the party as you write unit tests. The best example of that would be your own code, that multiples 1 with 1. If one of my developers did that in code, and told me "I implemented 100% coverage", I would chase the guy out of the building with a stick when I realised what he or she had done ...

Thread Thread
joelbonetr profile image
JoelBonetR • Edited on

Hahahaha πŸ˜‚ I imagined it and was funny.

Just pointing out that coverage measures test quantity and not quality even it's bringed over the table when talking about code quality. It it would be a test quality measure, a 100% code coverage codebase won't need regressions and we all know that's not true.

That was a dumb example but I've found things not much cleaver than that tbh πŸ˜…

Thread Thread
polterguy profile image
Thomas Hansen Author

coverage measures test quantity and not quality

True, but one speaks about the other, at least to some extent ...

That was a dumb example but I've found things not much cleaver than that tbh

^_^

Thread Thread
joelbonetr profile image
JoelBonetR

Agree

Collapse
lexlohr profile image
Alex Lohr

So your view is narrowed on your own use cases and from that you conclude that therefore, unit testing front end code was (probably) universally useless?

Unit tests have two main advantages to more involved tests: they are cheap and fast to run and closer to the code they are testing, therefore hopefully eliminating side effects, allowing you to spot issues faster and also to pinpoint their origins more precisely. They are not meant to replace integration or end-to-end tests, but like strict types a barrier for soundness issues, just for other things than types.

That being said, you are right that it's actually useless to test what had already been tested: you don't have to test that e.g. react or angular will render your front end at all or will call your event handlers on the events they were supposed to be bound to. These packages already have extensive test suites to ensure they work.

What you want to unit test is the edge cases in your units, the decisions, the logic flow. It may be small in your front end (it's much more complex in ours, which is a full blown meeting web app and a lot of the business logic runs in the front end), but unit testing it should still be valuable, even if not necessary in every single case.

Collapse
polterguy profile image
Thomas Hansen Author

These packages already have extensive test suites to ensure they work

Great point.

What you want to unit test is the edge cases in your units, the decisions, the logic flow

My point is that if you've got decisions or "logic flow" in your frontend, you're (probably) doing something wrong - Yet again, I write about general cases, not applicable to all cases, something I create an argument towards using Canva as an example.

even if not necessary in every single case

Change "every single case" to "what most developers are doing in most of their cases" and we agree here I think ...

Collapse
lexlohr profile image
Alex Lohr

My point is that if you've got decisions or "logic flow" in your frontend, you're (probably) doing something wrong

It really depends on your use case. But even if you don't have to manage WebRTC streams in the front end, having logic there can be advantageous for one of two reasons: being able to use the application while being offline temporarily and being a lot faster during times of slow connections. And that applies to most, if not all cases.

Thread Thread
polterguy profile image
Thomas Hansen Author

It really depends on your use case

Yes it does, and I accommodate for that, in particular as I mention Canva as one example. However, 98% of the use cases in the enterprise development segment doesn't need it, period!

Thread Thread
lexlohr profile image
Alex Lohr

I'd like to see your sources for that number, because I get the feeling that you just pulled it out of thin air.

Thread Thread
polterguy profile image
Thomas Hansen Author

that you just pulled it out of thin air

80% of software developers don't work for software companies, but companies having software development as a secondary function. This can be insurance companies, banks, hospitals, or any other company who's purpose it is to do something else besides delivering software. If you doubt that number, you need to do some research yourself. It's not only a factual statement, it's also an obvious statement ...

Thread Thread
lexlohr profile image
Alex Lohr

And another number that you very probably just thought up. And even if it was correct, after all is said and done, at the end of the day, your software or the software building on it is going to be used by humans. Worsening their user experience merely because you are opinionated against front end business logic is a recipe for bad software.

If you doubt that number, you need to do some research yourself.

So you also never heard about the burden of proof? Figures.

Thread Thread
polterguy profile image
Thomas Hansen Author

you are opinionated against front end business logic is a recipe for bad software

This I actually have scientific numbers on, even thought I can't remember the exact figures. I participated in a trend report for DZone a year ago, and if I don't remember wrong we had 650 participants, having 90% claiming they did not put business logic into the frontend. Which makes sense. Look it up if you wish. It's still out there somewhere ...

As to me "pulling number out of thin air" in regards to how many are working for companies having software development as a secondary function, this is a flawed argument, down the same line as some of your flawed argumentation techniques you yourself attacked in one of your article a couple of weeks ago ...

Thread Thread
lexlohr profile image
Alex Lohr

...we had 650 participants, having 90% claiming they did not put business logic into the frontend.

And this is an example of the argument from majority fallacy. First of all, the front end only became capable of reasonably running business logic within the last ~5-10 years. Second, this is also paired with a fallacy of composition: I could ask the same question at a front end conference and get a completely different result (granted, it wouldn't be representative, either).

this is a flawed argument

If you call something a flawed argument, you are required to show where the flaw is - as I do. The claim that you invented the number also is an assertion and not an argument, so your objection here is flawed and misleading, as it only explained why I was asking for sources.

Thread Thread
polterguy profile image
Thomas Hansen Author

If you call something a flawed argument, you are required to show where the flaw is

OK, let me summarise the flaw; "frontend business logic" - It really encapsulates the entirety of the problem ...

Thread Thread
lexlohr profile image
Alex Lohr

This calls for an example. The shopping cart is a crucial element in every web shop, driven by business logic. If its logic is solely handled on the server and the user has connection issues, it will simply stop working.

Now, if you extend that logic into the front end, you can ensure that the user still can use your shop without missing a beat and just notify him if some data changed after putting things into the cart once the connection is back to normal.

You're using front end business logic to solve actual user issues in that example. Failing to understand that limits your ability to create excellent software.

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

If its logic is solely handled on the server and the user has connection issues, it will simply stop working

Yes, but creating "unit tests" for a shopping card implies having to fake a user, with the entire DOM, and the whole shebang, using weird frameworks and tools, allowing you to automatically pretend that some automated process is a user. These aren't unit tests but something completely different.

The purpose of a unit test is the same purpose as the seat belts in a formula 1 car, which is to secure the driver such that he or she can drive faster, without risking their lives as a consequence. Hence, the foundation for unit tests is to (long term) increase velocity of project maintenance, without risking introducing new bugs.

If you start "unit testing" your shopping cart's behaviour, you end up not testing "logic" but rather CSS selectors, DOM manipulations, and GUI. This is first of all extremely difficult to automate, and more importantly results in reducing the velocity which you can maintain the project at, since even a microscopic change in your UI requires you to change and modify the "unit test".

Hence, your "unit test" (bad word for it really) is no longer increasing the velocity at which you can maintain your project but rather decreasing the velocity at which you can maintain your project.

Sometimes it helps to stop and ask yourself "why". If you did that with frontend unit tests, you'd see clearly as the sun that 80% of the time they're pure madness ...

Thread Thread
lexlohr profile image
Alex Lohr

Say, if you're testing on the back end, you don't have an operating system running underneath and libraries to support both your code and your tests and don't mock user behavior (i.e. requests, data, profiles)?

Also, we have 2022, in case you didn't notice. Running automated tests with a virtual DOM is rather simple now. Yes, you can be bad at unit testing front end code, but ignorance about something is not a valid reason that it is inherently bad.

Thread Thread
polterguy profile image
Thomas Hansen Author

Running "unit tests" relying upon the DOM is like saying "killing for peace". I've explained why in my former comment to you, and I don't like repeating myself, and you did not answer my concerns.

Thread Thread
lexlohr profile image
Alex Lohr

Let's agree to disagree. The DOM is merely the operating system of the front end. There's nothing complicated about testing in this environment.

Collapse
brense profile image
Rense Bakker

Hello, its 2022, not 1999. There's business logic in the frontend. The backend is only really used now to define a data model and talk to some persistence layer and to do authentication. The persistence layer is safe because you can verify in the backend if someone is allowed to make a specific change in the persistence layer, usually based on the data model and some authentication token.

Why we moved away from doing all business logic in the backend? Because user interaction is also business logic and if you have to go ask stuff from the backend on every user interaction, your user experience turns to absolute shite.

Collapse
polterguy profile image
Thomas Hansen Author

Let me guess? GraphQL ...? ;)

Collapse
brense profile image
Rense Bakker

GraphQL is a query language. It offers tools to facilitate this, but the implementation of your data model is still something you have to do yourself... How you implement the data model is up to you. There are a lot of good libraries that make it easier. A lot of people do role based authorization, but there are other options too.

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

Are you going to teach me RBAC and normalisation now too ...?

Seriously, if you're, and I paraphrase you now; "exclusively building business model in your frontend, while reducing the server down to authentication, authorisation and data storage" we have a serious problem. Or to be specific, your employer have a serious problem. To illustrate that, let me ask you a question; "How do you send emails from your frontend?"

I could mention a bajillion things not even possible to implement as business logic in the frontend, without opening up your server as a gaping security hole for all sorts of problems - But the above should get you started ...

However, my reasons for mentioning GraphQL was because of that GraphQL often tend to lead to such things as you are explaining, where all BL is on client, resulting in that your app is ipso facto one large security hole ...

Thread Thread
brense profile image
Rense Bakker

I never said all business logic should be in the client. The data model is also business logic, I specifically said to define the data model on the server... Also yes, there are definitely ways to send emails from the FE, not saying you should always opt to go that route, but its certainly possible... Serverless is a thing in 2022.

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

Serverless has about as much to do with frontend/backend business logic as CosmosDB has to do with SQL. Serverless is a method to create HTTP Web API methods (mostly, ignoring timer functions of course) that is (often) implemented as Kubernetes PODs, dynamically orchestrated on a "per needs basis" - I should know, we've basically implemented our ENTIRE COMPANY around the axiom ... :/

In fact, you can even have a "serverless application" without even having a frontend ...

However, you CANNOT get away from having "a server", the point about "your server" though is that it's not a statically scheduled server that is "only yours", it's a technology typically built upon Kubernetes allowing your cloud provider to orchestrate and schedule execution on a "per need" basis, using stuff such as K8s replicas, sleeping containers, etc ...

If you believe that "serverless" is about "not having backends, but putting all your business logic in the frontend" I would recommend you read up on the subject ...

Thread Thread
brense profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Rense Bakker

Stop changing the subject. What you asked was this: "How do you send emails from your frontend?", answer: serverless functions are a thing and serverless functions can send emails, also plenty of cloud solutions out there: mailersend.com/features/smtp-relay So yes... thats how you can send emails from your frontend without having to maintain a server. Not saying thats what you should do, but thats the answer to your nonsense argument that you cant do business logic in the frontend.

Also... Wow! You're an arrogant asshole :B

Thread Thread
polterguy profile image
Thomas Hansen Author

serverless functions are a thing and serverless functions can send emails

Serverless functions are backend code! You're the one who's changing the subject ...

Check up Azure Functions or Lambda Functions with AWS before you make a fool out of yourself here ...

Thread Thread
brense profile image
Rense Bakker

I never told anyone not to write backend code. I said most business logic resides in the frontend nowadays and that backends are typically only used to define a data model and do authentication.

We have a real problem here though:

A: According to you, emails have something to do with business logic? Or why else did you bring it up?

B: Serverless functions have nothing to do with business logic (your words)

C: Fact: you can send emails with serverless functions

A, B and C can't all be true... So what's it gonna be? Either A or B has to be false since C is a fact. Or are you one of those people who believe in alternative facts and you're just going to ignore the fact that you can send emails with serverless functions?

Also, there's a lot of other ways to deploy serverless functions besides Azure or AWS.

Thread Thread
polterguy profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Thomas Hansen Author • Edited on

I said most business logic resides in the frontend nowadays and that backends are typically only used to define a data model and do authentication

I am really quite honestly speechless, and I'm not really sure what to say anymore to be honest with you. I suggest we both stop commenting before you apply permanent damage to your ego, to the point where you can no longer recover, and are forced into defending a poisonous position for the rest of your life as a consequence ... :/

Just my two cents here really. If you want the last comment though, go ahead, I will not answer you anymore, it's really futile the way I see it at this point ... :/

Edit - However, with that position you'd love Magic since it does all of the above 100% automagically (data model + authentication). Personally, I would never encourage anyone to write BL in frontend, but what do I know ... :/

Collapse
ecyrbe profile image
ecyrbe

I beg to differ.
Front end testing is about testing front end behaviour:

  • front-end visual accessibility with axe,
  • front-end keyboard accessibility with bdd testing,
  • and usually all front-end behaviour testing with bdd
Collapse
joelbonetr profile image
JoelBonetR

UI testing, Usability testing, Accessibility testing etc are not limited to BDD nor is necessary to follow BDD to bring them on a project, be that TDD, BDD, ATDD, whatever other bunch of uppercase characters glued together or none of them.

And of course we've logic living in the frontend that does belong to this context and needs to be unit-tested as well if you want to build confidence in your code.

Collapse
polterguy profile image
Thomas Hansen Author • Edited on

Normally I'd agree with you, if it wasn't for the fact of that we built this without a single unit test in our frontend code. I suspect it's several orders of magnitudes more complex than what the average enterprise software developer has ever created ... ;)

Thread Thread
joelbonetr profile image
JoelBonetR • Edited on

I also built complex codebases without testing by client decisions (which I find wrong and later issues proved me right), all of them being on the market up and running.
Glad I'm not the one maintaining it.

Btw your link sends me to a 404 inside GitHub (private project or wrong link) so I can't evaluate the complexity.

Even that a successful development is not proof for anything.
There's a high probability you still find issues in the future when adding more use-cases to pre-existing features or features that are dependant on them.

You can solve or spot them on any stage before production but it will be by manually testing.

You just didn't automate the tests, but you are still testing it by hand which is not the smartest move and you'll notice it the first time a bug appears in production.

Adding a console.log is testing (that some variable has some value), adding server logs is testing, checking the UI manually is testing as well. The question has never been to test or not to test. The question is on how you test.

Thread Thread
polterguy profile image
Thomas Hansen Author

Oops, sorry, wrong link - Edited it now ...

The above thing seriously doesn't have enough logic in the frontend to justify creating unit tests for it, which might come as a surprise if you see its features, and/or try it out ...

Of course, it's built upon the same thing we've got 1,000+ unit tests in the backend for ...

Thread Thread
joelbonetr profile image
JoelBonetR • Edited on

Sorry I'm on the phone and hit send too early, edited the comment before πŸ˜… (and now checking your link)

Edit:
Yup, this client code is really short, it can probably avoid most logic that a usual webapp has plus with some more E2E (apart from those sanity checks I saw) you'll cover it entirely or mostly like it was BDD.

I think we can agree that it's not the case of an usual webApp in which you'll have logic about what someone can see depending on it's role/permissions, multiple user journeys depending on X or Y, sometimes A/B testing (being created in-house or by some third party tool), content based on user preferences and so on. (Some of those needs to be double-checked by the backend of course, but the double is not silent).

Avoid testing on this situations can become a mess quickly. And even if it doesn't, my experience says that you'll get a hard time with what HHRR people categorises as "retaining the talent" πŸ˜‚

Thread Thread
polterguy profile image
Thomas Hansen Author

which you'll have logic about what someone can see depending on it's role/permissions, multiple user journeys depending on X or Y ...

All of these, and more, is to be found in Magic ... ;)

Thread Thread
joelbonetr profile image
JoelBonetR

Created prograMagically I guess 😁

Thread Thread
polterguy profile image
Thomas Hansen Author

Hehehe :D

Yup!! ^_^

Collapse
llorx profile image
Jorge Fuentes

This post is nonsense.

Front end tests also involve automatic screenshots and comparison with a base to check that you did not fucked up a component style.

Or when you want a specific component to be visually hidden or shown depending on whatever logic.

Or even to test the basic "you are sending the username and password correctly when clicking the login button".

Logic exists in the frontend, and because of that you should test it, each line of code if you want truly 100% coverage, although the frontend is only the 5% of your full project.

If you return to the pure HTML and zero JavaScript frontends like in the 90's then you MAY have a point.

Collapse
polterguy profile image
Thomas Hansen Author

None of your above examples were unit tests by the very definition of the term unit test. Possibly your "sending the username and password correctly" maybe, which would require a mock object to avoid touching networking though, but besides from that, none of the stuff you're giving as examples are unit tests ...

Collapse
llorx profile image
Jorge Fuentes • Edited on

A screenshot of a very specific component is a styling unit test. Search for "CSS unit testing" on Google.

"None of what you said is unit testing, apart of the things that are unit testing" xD

I get the "business code in the frontend" thing, but the same way in the backend you have things and interfaces to those things and you test everything as "testing backend code is good", a frontend is just an interface for a backend that also should be tested as it may have been implemented incorrectly, for example. More than "frontend and backend" is a "server and client", and a client needs to be tested. The thing with frontends is that they are stylish and visually cool clients.

I hope that you don't dare to create a pure backend client to another service (socket, rest, whatever) and you don't test it.

Thread Thread
polterguy profile image
Thomas Hansen Author

OK, so if I changes the colour of my button my unit test fails? How is that productive really? I answered another guy here that the purpose of unit tests is to increase long term project velocity. Having unit tests that needs to be updated every single time I apply a UI change, is like having a formula 1 car with a permanently opened parachute hanging behind it.

Unit tests shouldn't even touch networking my friend. Add "screen shots" to it, and I have no word for what it is, but it certainly isn't "unit testing" ...

Thread Thread
llorx profile image
Jorge Fuentes

If changing a button colour intentionally breaks your tests, that means that you don't know how to create proper CSS unit tests. You can't complain about something that you have never used, so you are just failing with noob guessings and thinking that something is bad because you have not experience with it, at least enough experience.

For example, in a UI you always have predefined colours. You never have a single button with a forced specific colour if it doesn't come from a "master list". SCSS comes really handy for this (although there are also CSS variables).

If you change a button colour, you actually modify that master list. Is a good practice to have it. The objective is to be able to modify almost the entire styling by just modifying those variables instead of fiddling inside the CSS code. All those variables are the ones you will be able to test properly, so you can forget about them in the "manual" testing (yay). The more you add, the better (roundness of a button? padding between elements? Element display depending on a condition? I don't know, whatever thing you could think of).

Then, you can match the UI colours to that master list. If you want to change a button colour, you change the corresponding colour on that master list, so your tests will drink from that table.

If you add another class to a button, or to a button parent, or modify the box-sizing by mistake, styling tests will fail, because the tests expected that button to have a CSS output that you previously saved in your first manual test.

It follows the basic principles:

  • Tests are automatic.
  • Tests can be unitary.
  • You don't have to modify tests for them to inherit changes on purpose.

Obviously if you modify the master list by mistake, is going to be more difficult to detect, but being a master list is not a bug if you modify the main selection color to "red" instead of "blue" as the owner asked, as the main purpose of the master list is to reflect to the UI the values that you selected. You may have a "master list validator" which checks that the master list contains the company colours, but well... this is a bit weird xD

The good thing is that is saves you from small mistakes that could happen from modifying the styling or HTML, specially those that move a single pixel, modify a button hover, or modify a 1px border, which are more difficult to detect. In reality, you are testing that the CSS that you want to apply is the one actually applying, even on different screen sizes, and it helps.

Is more difficult to do CSS testing than code testing, but is testable to a level where you can start to discard manual tests, which is the main point of all this.

Thread Thread
polterguy profile image
Thomas Hansen Author

The first time I did GUI testing was in 2001 my friend. It was for a GUI library called SmartWin. Since then I’ve used Selenium, and all sorts of tech in this space. All have one thing in common, the reduce project maintenance velocity, without providing the required security net. But, it’s quite irrelevant. The thing you’re describing as unit tests have never been unit tests, and will never become it either. Regardless of terms, it’s still like having a constantly mounted parachute hanging out from behind a Formula 1 car, and hence by the very definition of the term contra productive, providing the exact opposite result of the intentions behind unit tests …

Thread Thread
llorx profile image
Jorge Fuentes

I've known developers for 20 years that still have duplicate code in their projects. Doing something a lot or since my grandad was a teen doesn't mean that you are doing it properly. Specially when you say that you had problems with that since then and didn't ever fixed them in any way.

I know how I do my front end testing, and the day I got used to it and thought deeply what I wanted to achieve, I had any of those problems, because we are lucky that in our world, almost any programming problem can be fixed with enough focus. My front end tests are not counter productive, but whatever. I don't have 100% coverage, but great part of the manual labor is now gone, without any development complication.

Is like saying that OOP or functional or so and so paradigm is bad because I'm having problems, which are actually not good coding skills on that, because of lack of experience or lack of interest on improving.

Your post is a big red flag actually, so whatever.

Thread Thread
polterguy profile image
Thomas Hansen Author • Edited on

I've known developers for 20 years that still have duplicate code in their projects

FYI, I literally wrote the manual on DRY

Doing something a lot or since my grandad was a teen doesn't mean that you are doing it properly

That statement has literally been scientifically disproven by research. I could point you the way, but it's too late, so I'll just give you a hint; 10,000 hours ...

Specially when you say that you had problems with that since then and didn't ever fixed them in any way

It's not "me who has a problem with this" it is literally everybody who has a problem with it - Some of us just (still) live in denial ... :/

can be fixed with enough focus

Everything that requires "enough focus" is fundamentally broken. If your code, framework, language, or library of choice forces me to think, it is fundamentally broken!

Thread Thread
llorx profile image
Jorge Fuentes • Edited on

I didn't say that you write duplicated code. What I'm saying is that after 20 years since your first GUI test, you are still failing in a very obvious way. I think that you are talented in other programming fields, but in the frontend... I have my opinion here.

Internet is also full of big red flag posts about OOP or about functional programming, because "everybody has problems with it", but they are just bad quality code that leads to problems. And this applies perfectly here. In Spain there's a saying: "problem of many, fool's consolation".

With "enough focus" I mean to not live in denial saying "this is shit, and specially because other programmers also have the same problem", but instead to actually think what you want to achieve and how. Is not a code, framework, language or library. Is a FIXABLE PROBLEM that you are leveraging to a MANUAL TEST or even worse: NOT TESTING it at all. It says a lot about your code quality ethics. Looking at your website aista.com, you receive slaps on the first double-load, so...

Keep on writting big read flag posts while having a buggy website. I'm out here (muting the thread) and your obvious fool's consolation. Not going to waste more time.

Bye.

Collapse
jackmellis profile image
Jack

Oh boy you lost me pretty early on there! As somebody whose job is 99% front end business logic I beg to differ on pretty much everything you say.
I think this might just be a sweeping generalisation based on a handful of basic uecases, or perhaps a clickbaity-piece intended to ruffle feathers πŸ‘€

Collapse
polterguy profile image
Thomas Hansen Author

It seems that you are right, implying the exception to verify the rule. 80% of software developers works for companies who's job it is to deliver software as a secondary function. These are administration types of apps, CRM systems, etc. Adding business logic into these apps is madness. I have no idea what you're working with, but I give a use case myself in my OP about Canva, and how it would make sense to have unit tests in such types of applications.

However, for 80% of all software developers world wide it makes ZERO sense to add unit tests in frontend code ...

Collapse
ecyrbe profile image
ecyrbe • Edited on

Just to complete why you may want to frontend testing, two minutes of looking at aista.com :

  • website is doing double loading (perf)
  • tabulation order is out of the box (usability)
  • menus don't have click away behaviour (usability)
  • links don't indicate state (accessibility)
  • etc

Frontend testing are to automate and checking those. If you don't care about those, guess we don't have the same definition of frontend quality.

edit: fix typo

Collapse
polterguy profile image
Thomas Hansen Author

Fontend testing

It would be a nice start if you spelled frontend correctly, such that we knew we were talking about the same thing at least ... ;)

Collapse
llorx profile image
Jorge Fuentes

He is talking about the definition of frontend quality, so yeah, you are not talking about the same thing ;-)

Collapse
thumbone profile image
Bernd Wechner

I have certainly experienced (and written) frontend presentation and form management code, that would benefit from automated testing (Selenium as a rule) or unit testing if that's the preferred term (as the tests are defined in little bits, of targeted testing so that if it breaks - i.e. an expectation is not met, it's easy to find the code to blame.

But yes, that is the only code I would generally like to see client side really.

Collapse
polterguy profile image
Thomas Hansen Author

Yes, but these aren't technically unit tests. When I've done similar things though, I tend to struggle with changes in the code as a part of the requirements breaking my tests, which is kind of my exaggerated point here, that tests are most valuable when you can modify the code and drive it forward without breaking your tests ...

However, I wrote this article series mostly to make people think, which is why I ended it with a Lada is better than a Ferrari :D

Collapse
thumbone profile image
Bernd Wechner • Edited on

To be honest, unit tests should only really focus on stable requirements or code upon which other code depends. They are a cementing strategy to monitor, and implicitly demand stability in the things tested. Perforce that is not ideal for code which is changing a lot (being developed) unless, adding the overhead of evolving tests alongside the developing code is a choice invested in (TDD would argue writing the test first even, but I've not found many investing in the cost of TDD). Myself, am coding a pile of unit tests on core code, on a project as its large enough that new developments risk breaking things unintentionally (or better said that ever present risk has crossed a threshold of tolerance and so investing in cementing tests has reached the top of the to-do list).

Collapse
uzitech profile image
Tony Brix

Sorry I am repeating some things from other commenters. These are the issues I see with this article:

  • There are many valid reasons for business logic to be on the front end. I have many apps that don't have a "backend".
  • If you don't have logic in the front end than why are you using angular? All logic should be tested not only "business" logic.
  • unit testing for how the front end is displayed in different browsers should happen more often. (I know that is not really what you are talking about but it is still a front end unit test that is not useless)
Collapse
polterguy profile image
Thomas Hansen Author

unit testing for how the front end is displayed in different browsers should happen more often

These aren't unit tests, something others here have also pointed out - Implying it's a different debate, arguably with overlapping arguments though ...

Collapse
uzitech profile image
Tony Brix

I suppose "unit" could mean different things to different people. In our display tests a "unit" is just one state the frontend could be in.

But like I said, not really what this article is about. Just one thing I thought of when I read the title.

Thread Thread
polterguy profile image
Thomas Hansen Author

Thank you, it's a valuable comment too :)

Collapse
framirezsandino profile image
framirezsandino

I think this is a very controversial statement as previous posted comments have proven so far, but still, want to add my two cents. Before thinking on making UI Unit Testing you should think about if it is worth doing it, or, it is made to cover a design flaw in the app overall.

Let me use an example: let's say you have to provide a presentational message in UI to convert an input entered number by use into words, something like libraries such as npmjs.com/package/number-to-words do. Let's suppose you have to implement it from scratch and incorporate this functionality on UI only, as this value doesn't have neither to be persisted or used on BE services. In that case, you would need to ensure the UI implementation for a theoretically called numberToWordsInEnglish being called this way:

numberToWordsInEnglish(1000)

Will always produce as output:

"one thousand"

Instead of "one zero zero zero", "ten zero zero" or whatever other combination considered wrong under this context.

Also, let's say your initial implementation doesn't support decimals and what them to be added later, or maybe extended maximum number support. You may want to have a mechanism to validate any future change doesn't break the current implementation that, if made in smaller funcional pieces, can be tested only once using unit testing.

Now, for a different example, if you need to test the place you're placing this" number to words" message is correct, or, using enough contrast, or, even if the message is present at all in the app requires different testing techniques, such as E2E testing, integration, components, etc, that may not be considered unit testing at all, which is something several detractors of your post doesn't seem to differentiate correctly, as they seem to extrapolate the term "unit" testing to "any kind of" testing.

TL;DR correct testing depends on context, if you forcibly have to test logic in UI for whatever reason it is, you should go with unit testing, otherwise, you should apply other testing techniques and not to mix them up with what "unit testing" is actually intended for

Collapse
polterguy profile image
Thomas Hansen Author

TL;DR correct testing depends on context, if you forcibly have to test logic in UI for whatever reason it is, you should go with unit testing, otherwise, you should apply other testing techniques and not to mix them up with what "unit testing" is actually intended for

Thank you!

For the record, there are edge cases where unit testing frontend code makes sense. I even give an example myself.

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.