You need to sign in to do that
Don't have an account?
How do you organize your testing classes?
This is more of a best practice type question. For a long time, I had a seperate testing class for every trigger/component/class. This got to be kinda bulky, and I found I was repeating a lot of code (lots of triggers revolved around creating the same types of objects, so many of my testing classes where essentially the same thing, save a few asserts). So I thought it would make sense to combine all my testing classes into one massive test class. Easier to maintain (from my point of view), and made it so I just created my test objects, ran my various asserts and coudl easily test all my code.
Now of course, that idea is failing. I have to create too many objects, and run too many different tests for them all to be contained in one file. But the fact that there is a lot of shared code is still true. So now I'm thinking about breaking it into testing classes by the object they test. I'm really fairly new to OOP, so I know there is a more eloquent way of doing it, probably creating some basic classes, and extend them for the various objects I need to test or something. Before I do another rewrite though I just wanted to see how the community does it. Thanks for any insight.
No, you're on the right track. There's no hard and fast rule for how to categorize your tests into different test classes. You can certainly factor out common initialization code into static methods that you call from multiple tests. There's nothing in Apex akin to the TestCase base class in JUnit, with its setup/teardown methods (that's something I'd like to add at some point).
Basically, I think you're already going in the right direction.
Rich
So you are thinking basically one testing class for each kind of object makes sense then?
My issue right now is that I'm running into governer limits on my big test class, so I need to break it down. By object probably makes the most sense right?
Which governor limit? Just the size of the class?
By object is one common approach, yes. It really kind of depends on what your app looks like.
In this, case it's too many SoQl queries (101). There is just so much querying going on while testing all the triggers it explodes. Just happened today after I tried to add one more test case.
I'm a little confused. You have one big class for testing each object, but you still have lots of individual testmethods inside that class, right? It seems like you shouldn't run into governor issues, since each testmethod runs within its own context.
If your one big class is also one big testmethod, that will definitely cause problems.
Jeremy
The essence of test classes is that you break down each test method to only test a single unit of your code logic... hence the term "unit test".
You can try to combine your test setups into a single class. By that, I mean to put the code used to set up your test environment into a class that can be shared by many other test classes.
Then in your test class, you can call just the test setups that you need to test a particular unit of code.
Each test method of your test class should be testing a single unit of code logic. By doing so, you will avoid needing to do excessive querying and going over the governor limits.
Hope this makes sense.
Jeremy,
It's one big class, cause I suck at programming.
It is attached so you can see what I mean.
Ah, yes. You should try and break that up into multiple testmethods. Then it doesn't really matter if they're on one class or not (except that the total class size cannot exceed a certain size, but that will be obvious when you try to save).
You're also not doing much in the way of asserts. Having asserts in your tests are how you know if the code behaves the way you expect it to. I'm seeing a few instances of this anti-pattern:
try {
insert a;
}
catch (Exception ex) {
System.debug('it is good that this failed');
}
Now, if it didn't fail, you wouldn't see the debug msg, but the test method would continue running and you wouldn't see any sign of failure when the test is done. What you want is something more like:
try {
insert a;
System.assert(false);
}
catch (Exception ex) {
System.assert(ex.getMessage().contains('My Validation String')); // where 'My Validation String' is the reason for the insertion failure
}
This way, if it succeeds, or if it fails for the wrong reason, the test will fail.
Ok, yeah I'll work on breaing it into multiple methods.
I know I need to do more asserts. I'm just so lazy, and overworked :P You know how it goes. The code works fine so I just try and deploy and get it out. I know they are important though, so when I refactor it into using more methods, I'll try and at least get a few asserts in there.
It's always tedious to go back and write testmethods and asserts after the code is all finished. And of course, users are always in a hurry to get their functions working. However, developing a good habit of writing basic testmethods *at the same time* as writing the Apex code can really pay off. If you know in advance that you need to cover 100% of your code, you can be thinking about it and writing it almost simultaneously.
Some will even tell you to write your testmethods before the actual code, so you sort of save the fun part for last. I'm not that patient. My own pattern is to code, save to server, write tests, save to server, write asserts, run tests. Repeat.
Jeremy
Thats a solid plan, and I really need to start doing it. I just gotta push back a little and say that projects are going to take just a tad longer so I can make sure I am writting my asserts and real meanigful tests. Thanks for your help.
So I've broken my code into classes. Is there an easy way to share data between the classes without having to do a ton of passing around. So say I create one account, and lots of classes are going to want access to that account, whats the easiest way to do that.
Basically I just created a bunch of classes that create the testing data, and then other classes that actually use that data. I figured it would be much more efficient if I could call the class that creates the data once, and share that around, instead of every class that needs that data having to get it's own copy of it. Would marking the classes that create the data as public static work?
Use Test.startTest() and Test.stopTest() system methods in your test methods. You can use only once in every test method.
All of the code before the Test.startTest() method should be used to initialize variables, populate data structures, and so on, allowing you to set up everything you need in order to run your test. After you call this method, the governor limits that get applied are based on either the first DML statement (like INSERT, DELETE, and so on) or the first Web service invocation.
Lots of good advice here already. A couple of points:
1. Unit tests should test units of code - sound advice, but what is a "Unit" exactly? This is an exercise in experience IMO, but I try and write test methods for each method I have. I usually end up with a test class for every class with multiple test methods. However, this approach has it's limitations (see 2!)
2. How you test depends on what you are testing. Apex classes with public methods that maybe take a value and return a value based on the value passed in are very easy to test. Visualforce pages aren't necessarily as easy. Triggers... let's just say I dislike these the most, especially if you have a lot of objects to set up before you can insert/update/delete the object the trigger is on.
3. Reusing parts of test methods. See this post by the every-excellent Jeff Douglas to see how you can use static blocks of code across tests in a test class. You can have testMethods within your test class that insert setup objects and return objects but they can't take arguments; you can have static methods in a test class that do take arguments but (I believe) this will require coverage. Finally, you can create a "normal" class with a bunch of static methods that set things up and are callable from other classes (unlike the other two options).
4. I tend to write code that covers a particular part of functionality and then write tests for it, before moving onto the next piece that needs coding. Over time, I try to curate the test methods so that I'm reusing as much as I can.
good advice everyone, thank you. I think when I get my code all rewritten I might post here and see if anyone can point out and glaring errors or issues. I've been a procedural programmer for a long time, but still new to OOP concents and how to use them. Getting better though! Thanks again everyone.