I learned the foundations of theoretical computer science in university. I agree with the sentiment of this post, though it is hard to perform in practice.
In addition to pre-conditions and post-conditions, I would like to emphasize that loop invariants and structural induction are powerful techniques in CS proofs. https://en.wikipedia.org/wiki/Loop_invariant , https://en.wikipedia.org/wiki/Structural_induction
These notes from UofT's CSC236H are on-topic: https://www.cs.toronto.edu/~david/course-notes/csc236.pdf#pa...
Those notes are great, David Liu seems while a wholesome dude https://www.cs.toronto.edu/~david/research.html
UofT mentioned! Let's go!