It's hard to suggest something without seeing what you've got and what's being criticized.
Just a tiny idea on how to make your test-cases more general: try to make use of some kind of repositories.
These can be UserRepository (having GoodUser, BadUser; GoodUser.Admin, GoodUser.Customer, etc).
Such strategies are applied in automation testing.
This way, instead of having
1. Enter "Login1" into 'login field';
2. Enter "Password1" into 'password field';
3. Press 'Sign in' button...
You'll simply have
1. Sign in as GoodUser.Customer;
And if you have some other field added to the login process later, you won't bother editing dozens of test-cases.
List of Software Test Estimation Techniques you can use:
Work Breakdown Structure
3-Point Software Testing Estimation Technique
Wideband Delphi technique
Function Point/Testing Point Analysis
Use – Case Point Method
At some point in their lives, projects begin to require support and testing. To do this, in most cases, they come to the distribution of assemblies on dev - stage - prod, where each element is a polygon with its own version of the code.
dev: developer's unstable polygon, for development. Errors, temporary offline, manual edits and so on are allowed.
stage: pre-prod polygon, for testing and error detection. Errors allowed, offline not allowed, fully automated roll-out using CI.
prod: "battle" polygon. Users come here. Its fall and found bugs are the reason for the decrease in bonuses for programmers / testers / devops.
Accordingly, each polygon has its own database, its own environment, and so on. Typically, this is a collection of separate virtual machines. There can be several polygons of each type, depending on the goals, it is allowed to raise a sub-dev-polygon using containerization directly on the developer's machine.
Also, for each polygon in the repository, its own branch is created, the commit to which should initialize the automatic deployment of the fresh release to the polygon. With prod, as a rule, they do not do anything, but I think this is purely for personal reasons.
I can guess based on the cases that we gave to our testers. (We really wrote a special application for this, with bugs, and gave it to testers, but that's the case). The tester's goal is not to find bugs (strange as it may sound), but to test the functionality. Accordingly, the test case does not have to find a bug (especially if it does not exist), it must check that the entire application works as it is intended. A trivial option for authorization:
Drive in the name
Drive in a digit
Drive in a name of 70 thousand characters
Drive in "nothing"
And so on .. There may not be bugs here (and should not be), but the key idea is that the functionality works.