Waiting on either climbed or descended just tests that the timeout method was entered but does not guarantee the end of the method was reached and the proper state was set in the other variables. These tests will occasionally fail for this timing issue.
Though not fancy, this kind of synchronization can work. We just need to move these variables to the end of the timeout method. That will guarantee that when either climbed or descended are set to true the other variables are also in a testable state.