Returning IQueryable will definitely afford more flexibility to the consumers of the repository. It puts the responsibility of narrowing results off to the client, which naturally can both be a benefit and a crutch.
On the good side, you won't need to be creating tons of repository methods (at least on this layer) — GetAllActiveItems, GetAllNonActiveItems, etc — to get the data you want. Depending on your preference, again, this could be good or bad. You will (/should) need to define behavioral contracts which your implementations adhere to, but where that goes is up to you.
So you could put the gritty retrieval logic outside the repository and let it be used however the user wants. So exposing IQueryable gives the most flexibility and allows for efficient querying as opposed to in-memory filtering, etc, and could reduce the need for making a ton of specific data fetching methods.
On the other hand, now you have given your users a shotgun. They can do things which you may not have intended (overusing .include(), doing heavy heavy queries and doing in-memory filtering in their respective implementations, etc), which would basically side-step the layering and behavioral controls because you have given full access.
So depending on the team, their experience, the size of the app, the overall layering and architecture … it depends :-\
I think what confuses you about EF is the database context. It allows you to query objects like a Repository and save changes in persistence like a Unit of Work.
You have a lot of work done with EF database context. All you have to do is segregate the responsibilities by creating specific repositories and a unit of work that share the database context and pesists all changes in presistence with a single save call.
Check this link about create Repositories and UoW in EF. It is clear and easy to understand.
Best Answer
You should be returning values because you need them not because it makes testing easier. That being said, it is more valuable to know if the operation succeeded since you already know what's going to be updated. If something goes wrong you can use exceptions to communicate it to the upper layers. Also, I don't think that returning a value representing the number of affected records would provide much value since you'll probably be updating aggregates that have updated children.