We use BDD scenarios, which describe the system's capabilities from a user point of view. We phrase them as:
Given <a context>
When <an event happens>
Then <an outcome occurs>
You can use any number of givens, whens and thens.
Given <a context>
And <another context>
When <an event happens>
Then <an outcome occurs>
And <another outcome occurs>
When <another event happens>
Then <yet another outcome>.
The BA usually writes these for us, but I've seen devs or testers write them in collaboration with analysts or business stakeholders.
You can either use a BDD framework like Cucumber, SpecFlow or JBehave to automate them, or the devs can implement them with a little DSL. Here's an example. This is a real scenario which runs against the GUI of a little C# pet shop.
The thing I love most about scenarios is that you can have conversations about different things that the system should do, asking if different contexts change the outcomes, whether there are any other important outcomes which have been missed, etc. Those conversations then generate new examples.
We don't automate everything, but we automate enough to show how the system behaves and give us a good chance of catching something breaking. For instance, we might show one or two pieces of validation but not check that everything is validated; that can then be done at a unit test level.
The scenarios are then also readable enough for a tester to follow them, and because we generate them before we implement the code, we get better estimates and higher quality code too. Off-shore teams have really benefited from having clear scenarios and the freedom to ask questions about them.