After the Cypress spec completes every test has one of the 4 statuses: passing, failing, pending, or skipped. Let's look into each status.
Passing
Passing tests are the best, aren't they? The have successfully completed all their commands, never failing any assertions. Our smoke test below is a passing test:

Note that a test can pass after several test retries. In that case the Command Log shows the attempts, but ultimately the entire test has finished successfully.
Failing
Good news - the failing test has found a problem. Could be much worse - it could be a user hitting this bug.

After the test fails, use the screenshot and the video to find the problem and fix it.
Pending tests
The placeholder tests we have written were marked pending. They did not execute because the user did not want them to run - the user did not write them. Slightly confusingly, if the user does not want an existing test to run, they can use the it.skip or xit syntax to skip the test or a block of tests. Cypress marks all these tests pending.
1 | describe('TodoMVC', () => { |
All 3 tests above are marked pending when Cypress finishes running the spec file.

So remember - if you (the test writer) knowingly skip a test using one of the above three ways, Cypress counts it as a pending test. The result will be known in the future when you enable the test again.
The status and the name "pending" comes from Mocha.js test engine that Cypress uses internally. See the pending tests section of the Mocha's documentation captured below.

Skipped tests
The last test status is for tests that the user meant to run, but these tests were skipped due to some run-time error. For example, imagine a group of tests sharing the same beforeEach hook. The hook executes the common commands. For example, we could visit the page in the beforeEach hook because every test needs to start at the page.
1 | /// <reference types="cypress" /> |
If the beforeEach hook completes and both tests finish, two tests are passing.

But what happens if a command inside the beforeEach hook fails? For example, let's pretend we want to visit a non-existent page /hmm instead of the /. If we change our beforeEach to fail:
1 | beforeEach(() => { |
When Cypres starts executing the first test, the beforeEach hook fails. Now the first test is marked "failing". BUT if the beforeEach hook failed once, why would we execute it again before the second test? It would just fail the same way! So Cypress skips the remaining tests in that block, because they would also fail for sure due to the bad beforeEach hook.

If we collapse the test commands, we can see the empty box marking the skipped test "adds 2 todos".

The tests that were meant to be executed, but were skipped due to some run-time problem are marked "skipped" by Cypress.
The same situation happens if instead of the beforeEach hook, the before hook fails.
1 | /// <reference types="cypress" /> |
The Cypress Test Runner fails the first test (the one that really executes the before hook), and skips the rest of the scheduled tests.

Hope this explanation clarifies the Cypress test statuses.
Bonus: track the test statuses over time
I have described in the blog post Writing Tests Progress how to start testing the project by writing a lot of pending tests and then fill the tests with actual implementations.