The main trick of using stepper motors is to set a reliable reference point and size and configure your system to keep track of steps with controlled movements and acceleration. The main trick of detecting if you have lost steps reference is to compare the planned position with a sensed position.
As @JCA34F mentioned, actual motors move with acceleration/deceleration. You need to decide how you want to control acceleration. My test stops sending step pulses since mystepper.run() depends on there not being tooMuchPositionalError. But if the motor was moving at high enough speed, the inertia of the motor would keep the motor turning and skip steps. As would crashing into a hard physical stop while the controller was still sending steps. Both AccelStepper and MobaTools (and other acceleration-capable libraries) have a stop() command which slow the motor with the configured acceleration to avoid skipping steps. Both libraries also have a get-current-position function.
There are some good examples in the AccelStepper and Mobatools libraries -- AccelStepper has some overshoot demos, and Mobatools has some limit switch/reference demos:
Note that the mobatools reference examples use the reference once to record position, and afterwards uses the internal, calculated position. If you design your system to hard stop and re-reference itself at every cycle when it touches the limit switch, you won't be detecting lost steps, you'll be ignoring any lost steps and might add the repeatability error of the switch to your positioning process.