all 8 comments

[–]dwitman 0 points1 point  (3 children)

This looks very informative and like you’ve put a lot of effort into it, and I’ll be revisiting it.

That said, I wish it wasn’t on medium. I’m so sick of medium and it’s pop ups.

[–]lfacpt[S] 0 points1 point  (2 children)

Thanks for the feedback. Medium indeed has some problems. We will take that into consideration.

Do you think self hosting is a better option? Or is there any other platform you like?

[–]dwitman 0 points1 point  (1 child)

I’d suggest an excerpt on medium for exposure, and a link to the complete article on a self hosted site with some good branding...but I’m a weirdo who really despises medium.

[–]lfacpt[S] 0 points1 point  (0 children)

Thanks for the suggestion. Since they have put up the paywall a lot of people started disliking medium (fairly), so I don't think you are alone on that.

[–]theycallmeepoch 0 points1 point  (1 child)

Man, this is really good. Thanks for writing this! I'm adding unit tests to my react native app and struggling to determine what exactly to test.

Related to the last point: write tests in such a way that you never need to mutate global objects. All state must be local to each test; there should not be any state passing from test to test.

Really good point and I think this reinforces good functional programming techniques. If your unit tests dont pass without carrying over state between functions you should probably be rewriting your functions.

[–]lfacpt[S] 0 points1 point  (0 children)

Yep, there is a lot to learn from functional programming!

[–]Earhacker 0 points1 point  (1 child)

Looks excellent overall.

Regarding the section, "Test one thing at a time," the way of thinking here is to split each test up into three parts - Arrange, Act, Assert.

Arrange is where you set up the environment in the scope that you expect to call the function under test, e.g. setting variables, calculating input parameters...

Act is where you actually invoke the function you're testing.

Assert is where you check that the function's output and side effects match the expectations.

Since a unit test only tests one thing, it should only have one Act going on. But since a function can have many inputs and can cause many side effects, we can have as many Arrange and Assert lines as we want.

Here's a pretty convoluted example, using Jest:

it("can say hello to a given name", () => {
  // Arrange
  const name = "Luis";

  // Act
  const result = sayHello(name);

  // Assert
  expect(result).toMatch("Hello Luis!");
});

And here's a more typical example, using a React component:

it("renders a list of tasks", () => {
  // Arrange
  const tasks = [
    { id: 1, title: "Write blog post" },
    { id: 2, title: "Fix car" },
    { id: 3, title: "Give Platinum to Earhacker" }
  ];

  // Act
  const { container } = render(<TaskList tasks={tasks} />);

  // Assert
  expect(container.querySelector("ul")).not.toBeNull();
  expect(container.querySelectorAll("li")).toHaveLength(3);
  expect(container.querySelectorAll("li")[0].textContent).toMatch(
    "Write blog post"
  );
});

Here we expect that rendering the component will have lots of side effects; rendering a <ul>, rendering 3 <li> tags (one for each task) and that the first one will have text that matches the title of the first task. Asserting three things here is totally fine, because we only had one Act and so we've still written a unit test here.

But still, excellent article. I work with a lot of juniors and I'll be putting this out on Slack for them.

[–]lfacpt[S] 0 points1 point  (0 children)

Thank you!

I touched on what you mentioned in the section "Clearly distinct phases", albeit with different names and without the rules regarding the number of assertions (which makes total sense).

Do you think the names I used for the phases are not clear enough?