I have a static library in objective-C that has 1 main class, which is the delegate to multiple classes and includes delegate methods to handle server calls and location updates. Since I'm developing a static library, only logic unit test is supported. I'm having a hard time coming up with test cases. I read articles on unit testing that suggests not to test private methods and constructors. I wrote basic tests like testing a async method that makes an api call and checking the delegate method's return value. What is a good starting point when creating logic unit tests for a static library?
Since I'm developing a static library, only logic unit test is supported.
Actually, you can create a little app to serve as the test host. Then you're not limited to logic tests — you can test anything you want. You can test every aspect of your class.
Related
With C++ I like unit test functions or classes to be friends of the classes they test. That way I am not limited to the public interface. I need less mocking or boilerplate to test all methods. At the same time separating public and private methods.
With Vala is made most methods public to be able to test them. This exposes too much of the class interface.
Is there a way to make unit tests (classes or functions) friends like in C++?
I asked in this Vala chat(you can try it). The short answer seems to be no. There is a dead framework for testing ValaDate.
I have an F# library with lots of non-public stuff I want to test. Currently all code that is not part of the assembly's public API are marked internal (specifically, it's placed in modules that are marked internal). I use the InternalsVisibleToAttribute to make this code visible to my test assembly. However, in order to get the test assembly to compile, all tests that use internal types in their signature (most of them, since I use FsCheck to auto-generate test inputs) must also be marked internal (this needs to be applied to each function, because internal modules won't be discovered by xunit). Additionally, any types used exclusively for FsCheck generation (e.g. type ValidCustomer = ValidCustomer of Customer where Customer is my internal domain type) also need to be marked internal, and FsCheck seems to get stuck when creating internal types, so the tests don't run.
Is there any way to test internal F# code (from a separate test assembly) without having to mark all tests whose signature depends on internal types as internal? Right now I'm simply leaning towards not making anything internal at all in the original code, but ideally there's a way to have my clean-API cake and eat it too.
I've found that the OO world will generally be very opposed to attempting to test anything internal/private directly.
In the functional world I've seen more of a tendency to just expose public functions not intended for public use so they can be tested. See this comment from Edward Kmett.
When I started writing Haskell I started rethinking the way I used to approach encapsulation and hiding.
...
In general I'm a big fan of exposing all of the salient details, constructors and all for my data types through some kind of .Internal module, even if I want encapsulation and safety in the rest of the API.
...
As a side-effect of that you can then use these newly exposed guts to do nice testing. =)
There's a lot more detail in the original comment, and there is a talk where he discusses this at length but I can't find it now.
You could also give the module a really ugly name like __INTERNAL__ to discourage its use.
I am little confused with the benefit of protocols in VIPER architecture.
I understand that DI (Dependency Injection) achieved via protocols and helps avoid direct dependency between objects - I Agree.
But i am looking at a real benefit from usage perspective, an example may be - especially how protocols help benefit in unit testing (testing the Interactor portion).
Can't we achieve the same via method Callback's using blocks?
Hope someone can help me understand from usage perspective with some example
Cheers
Using a callback, e.g. from the Interactor to the Presenter, can make it harder to test the Presenter.
When writing tests for how the Presenter processes input (sent from the Interactor) your test would have to call some method on the Presenter that would cause the Presenter to make a call on the Interactor, which would cause the Interactor to send data to the Presenter.
By having the Presenter implement a protocol defined by the Interactor, your test can just directly call the appropriate input method on the Presenter.
As far as declaring protocols, I practice TDD in the style of mock roles, not objects (http://www.jmock.org/oopsla2004.pdf). The protocols help provide a better abstraction by focusing on what the object does (its role), not how it does it.
Protocols, on their own, are of little value for the unit tests. Your unit tests will provide test doubles (http://martinfowler.com/bliki/TestDouble.html) for the dependencies of the system under test. Even if you expose dependencies as concrete classes you can still create test doubles for your test.
In Objective-C, you can use a mocking library, such as OCMock (http://ocmock.org), or OCMockito (https://github.com/jonreid/OCMockito), to create stubs, spies, or mocks of the concrete class.
In Swift, you could create your test doubles by subclassing each of the concrete classes used as dependencies.
In short, protocols are not used to ease unit testing, but to describe at a higher level of abstraction, what the application does.
Here is an example of how having the abstract protocols were beneficial after the fact:
I created a protocol to represent the actions a user could perform on a screen, e.g. ProfileUserActions, that had actions such as changeName, and changeAddress. The Presenter implemented ProfileUserActions, and the View accepted a ProfileUserActions as a dependency. When the user tapped a button on screen, the View would send the appropriate message to its userActions object.
When I wanted to add analytics, I was able to create a new, independent ProfileAnalytics class which also implemented ProfileUserActions. I inserted the analytics object between the View and the Presenter, which allowed the app to capture analytics, without having to modify either the View or the Presenter.
By using a protocol it is easier for you to swap out an implementation in your VIPER structure. For example, you might have an interactor that is working with a class that is writing to the filesystem. You don't want to be testing the filesystem in your unit tests so instead if you put the filesystem write operations in your interactor behind a protocol you can then replace the filesystem write operations with an in-memory implementation.
As for a protocol on the interactor itself, I think it pays to be a bit more pragmatic about your choice. If it's easy to build your interactor for the test and it doesn't cause any side effects as part of testing then there's probably no need for the protocol. On the other hand, if you have to create a number of other dependencies then it might pay to have the interactor conform to a protocol so that you can more easily fake the output you get from the interactor.
I started with MVC quite recently because I heard that the major advantage of MVC is that it makes the application unit testable. After writing first unit tests I saw that it is not always simple to test controllers that have a lot of logic inside (send confirmation emails, use Session, context and other ASP Net statics). It takes me more time to write the unit test than the functionality and I am not convinced that this is useful.
I am tempted to move the business logic into a "Service" layer that eliminates of all ASP Net statics and which can be easily tested. Then to use Selenium for integration tests in order to test the whole functionality.
Did you got into the situation when testing an action is very complex (especially mocking the input and setting up environment)?
Did you find a good approach to have business logic in controllers. Or you found it better to use services and controllers code just relay on services calls?
In my opinion testing a controller is more equivalent to integration tests than to unit tests. What do you think about this?
Do you think that unit testing controllers has any advantage over integration tests?
I am tempted to move the business logic into a "Service" layer that
eliminates of all ASP Net statics and which can be easily tested. Then
to use Selenium for integration tests in order to test the whole
functionality.
This pretty much right here. If your controllers are complex then they need to be refactored. They shouldn't have any business logic at all. You can using a Mock framework to mock the service layer and test your controllers easily that way.
In my opinion testing a controller is more equivalent to integration
tests than to unit tests. What do you think about this?
I disagree with this. You are testing your controller to make sure it returns the appropriate response based on the input you give it. Supply an id that doesn't exist? Redirects to another page or returns a NotFound view. Model State is invalid? Returns the same view again, etc.
Did you got into the situation when testing an action is very complex (especially mocking the input and setting up environment)?
This happens when your controllers have lot of dependencies and they are tightly wired to them. Unless it is an existing code and bringing the changes to code creates more trouble you should loosely couple the dependencies through interfaces or abstract classes and that makes unit testable so easy. You should even use wrappers around Session, Cache and like objects.
As #Dismissile suggests that first you have to re-factor your controllers and then unit testing will be easy.
Did you find a good approach to have business logic in controllers. Or you found it better to use services and controllers code just relay on services calls?
Controllers are not the place to put business logic. All the business logic should be in the Model classes. The whole responsibility of the controller is to talk to the model and return a view, json or whatever back to the client. If you have complex business logic in the controllers you should move them to model classes.
Simply you should think about "Dump Views.. Thin Controllers.. Fat Models"!
In my opinion testing a controller is more equivalent to integration tests than to unit tests. What do you think about this?
Integration testing is totally different from Unit testing. In integration testing you have to setup the application and run the test cases against it. Here you are testing the behavior of the total application in every test scenario and not a single unit. Unit testing is all about testing the functionalities of methods in a class. Testing a class or method in unit testing should be independent of other classes or methods.
But the thing is when designing an application unit testing should be kept in mind else unit testing will become as difficult as integration testing and of course it's not unit testing at all.
Do you think that unit testing controllers has any advantage over integration tests?
Finding and fixing errors at unit level is so easy compared to the system level. So the answer is yes.
I think in your case you have an application that has controllers does more than what they have to do. So if you are thinking about unit testing so serious then you have to re-factor and loosely couple the dependencies wherever you need else there is no much gain in writing unit tests at all.
I am new to the whole unit testing stuff, so please excuse my lack of experience. I've read a lot of materials saying that no test should depend on others to do, i.e unit tests be completely independent form each other. Can you really do that in reality? I am having the following example: I have a few entity classes depending on each other, based on a certain database schema (I am using Linq- to SQL to generate them) Now, if I want to test each model class I have to build an object of the model class , build a test object of each of its dependencies, assign them to the object's properties and then persist the object before checking the context and asserting that it actually works.
This obviously makes it much harder to make tests that do not depend on each other, or do not run in a specific sequence (I do not an instance of type Content to be created before I have at least one instance of type ContentType) Dependency, at least on a model level is present and cannot be avoided.
Please, criticize me a lot, if you think that I am wrong. I want to learn.
P.S. Just to mention that I am working on an ASP.NET MVC app and testing with NUnit if that makes sense
Yes, you can really do this in reality.
The key to be able to isolate each unit is in writing loosely coupled code. Taking a dependency on LINQ to SQL (L2S) classes is not loosely coupled, which explains your problems.
You would be better off defining a set of interfaces behind which you can hide your L2S code. The Domain Model then works on those interfaces instead of directly on the L2S classes.
Yes, unit test should (and can) be independent. The problem you describe is about dependency. Dependency should be resolved using Dependency Injection frameworks (see AutoFac, Ninject projects).
The other thing is that your Database should be mocked using mock objects (see Moq, Rhino Mocks projects). You need to test all your code even if you database is disconected.
Other thing is that Unit test should test only one functionality not all your process.
What you describe here is not unit tests but integration test. Because the data model of your application is tightly coupled with the database your tests probably test the database functionality and not the "datamodel".
This is perfectly fine - just keep in mind that integration tests need setup (in your case database) and take longer to run.
You also probably have unit tests for your controllers that can be completely isolated from other components and do not need database to run, these are the unit tests you talk about.
If you do not test actual database functionality you can use fake/mock object to replace the external classes - in fact the tests created with the initial MVC project have an hand rolled fake objects along that do exactly that.
Another way to "isolate" your external dependencies is to warp the Linq2Sql code with your own class and fake these class calls using Mocking framework.