The error “List has no rows for assignment to SObject” occurs when query doesn’t return any rows.
Resolution
While a SELECT normally returns an array/list, these statements are using the shorthand syntax that assumes only one row is returned. What’s not obvious is that it also assumes that exactly one row is returned! Although this is unlikely to occur for Contact, it is highly likely to occur for any custom objects you create, especially when a WHERE statement is used that might return zero rows, such as:
Player__c player = [SELECT Id from Player__c where Name = :username];
if (player != null)
p = player.Id;
The above code will fail if there is no Player__c record with the matching username. It doesn’t actually return a null.
It would be safer to do the following:
Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (!players.isEmpty())
p = players[0].Id;
It’s one of those situations for which you would not normally think of creating a test, so it’s safer to just avoid the possibility.