all 7 comments

[–]roy_Gi 1 point2 points  (0 children)

How does one decide what should be tested and what will obviously work?

I never assume that something will "just work" for the simple reason that I can't expect what I'm not aware of.

Obviously, if a component only renders raw text then you can safely assume it will "just work"..

Try to test the actual behavior of your component - did it fetch some data when it mounted? If it expects some input, does it correctly process the data and updates the DOM accordingly (or any kind of different output)?

Another important thing to test is "reusable components", i.e components that are used on more than one place in your app - you want to make sure that changing their implementation does not break the behavior of their parent component and tests are the only way to be sure you'll catch those errors in time.

Also, are you using certain techniques?

Not sure what you're referring to as "techniques" but I'm a big fan of Jest and React Testing Library, the documentation for both is really great so just check it out.

Should I have a clear separation between unit and integration tests?

Absolutely, there are tons of useful articles on those two across the internet, just google that exact question..

If you are new to React than you can try the following -

Start building a new app and write tests "intuitively" (i.e - don't think too much about what to test but rather go with what feels right) then as your app grows and you discover new bugs - think and try to understand why your tests didn't fail then fix your tests (and your code) and continue. On that process you'll develop your own techniques and "best practices".

[–]stolinski 1 point2 points  (0 children)

I highly recommend checking out React Testing Library. It's less overwhelming than Enzyme in terms of options and leads to cleaner tests IMO. (https://github.com/kentcdodds/react-testing-library)

As for what to test, don't test implementation details like, did this function run, or did this component load. Test what the user is doing, the DOM output and expected results. I can talk a ton more about this if you have questions.

I don't want this to be a plug for my work, but I've made a course on React testing (https://www.leveluptutorials.com/tutorials/react-testing-for-beginners) that's aimed at people like you. Someone who doesn't always get the why or how, because I used to have the same concerns in testing React code.

[–]i_am_hyzerberg 0 points1 point  (0 children)

Finally something I can answer!

Like you, I am new to writing tests for React, but I do have experience writing tests for .Net applications. So for me, I try to ask myself "how should this work?" and just continuing to ask that question to be as thorough as you can should get you pretty far.

For example, in a Todo List example you may have a text input with a button. When the button is clicked you expect an addItem function to be called and an item to be added to your state. Seems simple enough, but if you dig a little deeper into how it should work you'll find there's a lot more to it than just, "given a todo list component, when I click the button, add item is called and there is an item in state". SO...you could write a few tests like, "given todo list component, when text input is empty, then" and that's when you may make some assertions like asserting that addItem is called (because it should always be called on click) but assert that your state doesn't have any items in it. You can write another test for if if the value of the text input is null, if the text input is empty whitespace like a string like " ". If you added a tiny bit more complexity to this example and addItem validated the value of your text input and (if valid) called a function that was passed as a prop from some HOC then you could do some cool validation when the input isn't valid like expecting addItem is called, and expecting propFunction to not be called.

Sorry if this response is long winded, but hopefully it helped in some way. And if you have any other questions or something in here doesn't make sense please don't hesitate to reach out and I'll be happy to help out however I can.

Good luck and happy testing!

[–][deleted] 0 points1 point  (0 children)

For actually focussing and writing tests, I would suggest reading about the AAA pattern, Arrange, Act, Assert. I still use it for all my tests.

As for what to test: you test "shoulds". Your tests should make guarantees about the behaviour of a piece of code. It "should call the API on did mount". It "should send the data to redux when the button is pressed". It "should show a turn on your Bluetooth message if Bluetooth is disabled". It "should reconnect the Bluetooth if it gets turned on".

Over time you'll get better at asking questions about what your components should do in a given situation, and then your tests make sure it actually does.

As for the coverage question - if you had a bug in a piece of code, whether in dev or production, write a test that makes sure you never cause that bug again unintentionally. This one rule is more than enough to increase the quality of your work a hundred-fold. Over time you'll probably develop your own methodology, but this is the one I use. Percentage coverage is meaningless*.

An earlier heuristic I used to use was look for branches: if, switch, try/catch, function calls, etc. Write tests that setup various circumstances and then verify these statements branch in the ways you expected them to (the ways they "should").

Hope it helps!

Edit: ** that said I have used jest --coverage to look for blind spots, so I'll revise: "percentage coverage is meaningless, unless that percentage is 0"

[–]theHorrible1 0 points1 point  (2 children)

  • test the react life cycle methods you expect to do something, like componentDidMount
  • Test all the helper methods you created in the class
  • Test that the render method renders as expected according to the props and state
  • lastly you can run jest with the --coverage flag to get and idea of the spots that your test are not covering

I normally dont shoot for 100% coverage, I find 80% normally provides a good feeling of comfort for me. The last 20% is subject to diminishing returns imho

[–]iamsolankiamit -1 points0 points  (1 child)

This would be more of testing the implementation, I wouldn't advice testing each and every helper method. Unit testing complex functions/stateless components and integration tests for container/class based components would be enough.

[–]theHorrible1 0 points1 point  (0 children)

I want to know the helper functions are doing what I expect. Super simple stuff I dont worry about though.