I’ve written a program in selenium webdriver but for my next project I would like to make it more maintainable by using better programming techniques. The main part I want to focus on is launching the browser once (1 session) and run say 10 different test then close the browser but I’m not sure how to do this. Using JUnit this is how I currently have my project laid out :
package example1;
public class TestBase { //main class
#Before
public void setup () {
//launch browser
}
#Test //all test run here
public void test1(){
login();
homepage();
}
#After
public void teardown(){
//close browser
}
}
package example1;
public class login(){
//do some action
}
package example1;
public class homepage(){
//do some action
}
package example1;
public class storeMethods(){
//all methods are stored which are then called by different classes
}
I’m not sure if the #Test annotation should even be in the main class or if it should be in its own class (login(), homepage()) because I read somewhere that test should not depend on each other. I don’t have much experience in java but I’m more than willing to learn. I just need some guidance on best practices and how to write good maintainable test so if someone could help me out or point me in the right direction then I’d really appreciate it.
While what Robbie Wareham said is correct, reusing the browser is not a good idea, you said that your overall goal is maintainability.
The techniques I've found to increase maintainability is the Page Object pattern with separate functions to interact with it.
The Page Object pattern separates the selector from the rest of the code. That way, if an element on a page changes, and your tests uses that element 5 times...you only change your code in 1 spot. It is also standard to include isLoaded(), which is a function that can be used to identify if you are already on the page you need so you don't reload the page.
I would also recommend having your test not directly deal with that Page you created. If you had a toolbar that you had to use to go to X page...and then the toolbar changed so the link you wanted was in a sub-menu, then every time in your tests you used that link, you would have to change the method to click on that link. Creating sets of selenium commands that interact with the page will make your tests high-level and easy to read.
I would suggest that reusing the browser is not following better automation programming practice.
Reusing the browser will result in unstable and unreliable tests, with inter-test dependencies.
In my opinion, it is far better to have atomic self contained tests.
If test runtime is an issue, then look at parallelism and using selenium grid
Related
I am having a hard time on how to start testing the integration with an external API ( Vimeo API ) for things like ( deleting a video - uploading a video - etc..).
Should I hit the real Vimeo's server while testing?
Is it a bad idea to do this like:
use Tests\TestCase;
use Vimeo\Laravel\VimeoManager;
class VimeoApiTest extends TestCase
{
protected function setUp() : void
{
parent::setUp();
$this->vimeo = new VimeoManager();
}
/** #test */
public function a_video_can_be_deleted()
{
$video = $this->vimeo->upload($fakeVideo);
// make http request to delete the video
$result = $this->vimeo->delete($video['id']);
$this->assertEquals('success', $result['status']);
}
}
In my eyes testing a package should not be your responsibility. Testing your implementation of the package is. Your example tests the package's VimeoManager directly. Which is in my opinion not what you should do.
Making a request to your API route that uploads the video is what you should test. During this test you do not want to upload it to the real Vimeo API, but you want to mock it.
Laravel includes a package that can do this, it is called Mockery. You can mock methods of classes to return a value without the initial logic being executed. In this case you would mock the delete method of the VimeoManager.
Laravel also provides so called Facades which can easily be mocked. I can see this package makes use of such facade. In this case you can do the following to test implemention of lets say your delete request.
/** #test */
use Vimeo\Laravel\Facades\Vimeo;
public function your_test()
{
Vimeo::shouldReceive('delete')
->once()
->with(...) // The parameters is should receive.
->andReturn(...); // The value it should return.
// Make the delete request to your API.
}
Well, you can test however you see fit. I've find it useful to have two types of tests.
A test which interacts with "something" else (service, system, etc...) is known as an integration test. These are nice and give some piece of mind, but are linked to the system that you are interacting with being online, this isn't always the case.
The second type of test can have a couple of different names, but that isn't really the point. The point of this second type of test is that you can "mock" out external/internal dependencies, ensuring that the "thing" your code depends on is online/behaves how you want. Mocking is when you manipulate a "thing" to respond a certain way. Usually, this is done via some framework or language feature. These types of test put a way larger burden on your code, and count more in my opinion.
I'm generally against mocking server to which my tests should be connected.
The main disadvantage of mocking servers and use simulators is fact that implementation of API may change (and for example throw exception/new status code or timeouts may be shorter) or there may be not compatibility between APIs between 2 versions of server.
Should I hit the real Vimeo's server while testing?
If You have possibility then create your local Vimeo's server using docker :)
Your tests will find out if something changes in API in future
I've been looking at the way unit testing is done in the NuGetGallery. I observed that when controllers are tested, service classes are mocked. This makes sense to me because while testing the controller logic, I didn't want to be worried about the architectural layers below. After using this approach for a while, I noticed how often I was running around fixing my mocks all over my controller tests when my service classes changed. To solve this problem, without consulting people that are smarter than me, I started writing tests like this (don't worry, I haven't gotten that far):
public class PersonController : Controller
{
private readonly LESRepository _repository;
public PersonController(LESRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var model = _repository.GetAll<Person>()
.FirstOrDefault(x => x.Id == id);
var viewModel = new VMPerson(model);
return View(viewModel);
}
}
public class PersonControllerTests
{
public void can_get_person()
{
var person = _helper.CreatePerson(username: "John");
var controller = new PersonController(_repository);
controller.FakeOutContext();
var result = (ViewResult)controller.Index(person.Id);
var model = (VMPerson)result.Model;
Assert.IsTrue(model.Person.Username == "John");
}
}
I guess this would be integration testing because I am using a real database (I'd prefer an inmemory one). I begin my test by putting data in my database (each test runs in a transaction and is rolled back when the test completes). Then I call my controller and I really don't care how it retrieves the data from the database (via a repository or service class) just that the Model to be sent to the view must have the record I put into the database aka my assertion. The cool thing about this approach is that a lot of times I can continue to add more layers of complexity without having to change my controller tests:
public class PersonController : Controller
{
private readonly LESRepository _repository;
private readonly PersonService _personService;
public PersonController(LESRepository repository)
{
_repository = repository;
_personService = new PersonService(_repository);
}
public ActionResult Index(int id)
{
var model = _personService.GetActivePerson(id);
if(model == null)
return PersonNotFoundResult();
var viewModel = new VMPerson(model);
return View(viewModel);
}
}
Now I realize I didn't create an interface for my PersonService and pass it into the constructor of my controller. The reason is 1) I don't plan to mock my PersonService and 2) I didn't feel I needed to inject my dependency since my PersonController for now only needs to depend on one type of PersonService.
I'm new at unit testing and I'm always happy to be shown that I'm wrong. Please point out why the way I'm testng my controllers could be a really bad idea (besides the obvious increase in the time my tests will take to run).
Hmm. a few things here mate.
First, it looks like you're trying to test the a controller method. Great :)
So this means, that anything the controller needs, should be mocked. This is because
You don't want to worry about what happens inside that dependency.
You can verify that the dependency was called/executed.
Ok, so lets look at what you did and I'll see if i can refactor it to make it a bit more testable.
-REMEMBER- i'm testing the CONTROLLER METHOD, not the stuff the controller method calls/depends upon.
So this means I don't care about the service instance or the repository instance (which ever architectural way you decide to follow).
NOTE: I've kept things simple, so i've stripped lots of crap out, etc.
Interface
First, we need an interface for the repository. This can be implemented as a in-memory repo, an entity framework repo, etc.. You'll see why, soon.
public interface ILESRepository
{
IQueryable<Person> GetAll();
}
Controller
Here, we use the interface. This means it's really easy and awesome to use a mock IRepository or a real instance.
public class PersonController : Controller
{
private readonly ILESRepository _repository;
public PersonController(ILESRepository repository)
{
if (repository == null)
{
throw new ArgumentNullException("repository");
}
_repository = repository;
}
public ActionResult Index(int id)
{
var model = _repository.GetAll<Person>()
.FirstOrDefault(x => x.Id == id);
var viewModel = new VMPerson(model);
return View(viewModel);
}
}
Unit Test
Ok - here's the magic money shot stuff.
First, we create some Fake People. Just work with me here... I'll show you where we use this in a tick. It's just a boring, simple list of your POCO's.
public static class FakePeople()
{
public static IList<Person> GetSomeFakePeople()
{
return new List<Person>
{
new Person { Id = 1, Name = "John" },
new Person { Id = 2, Name = "Fred" },
new Person { Id = 3, Name = "Sally" },
}
}
}
Now we have the test itself. I'm using xUnit for my testing framework and moq for my mocking. Any framework is fine, here.
public class PersonControllerTests
{
[Fact]
public void GivenAListOfPeople_Index_Returns1Person()
{
// Arrange.
var mockRepository = new Mock<ILESRepository>();
mockRepository.Setup(x => x.GetAll<Person>())
.Returns(
FakePeople.GetSomeFakePeople()
.AsQueryable);
var controller = new PersonController(mockRepository);
controller.FakeOutContext();
// Act.
var result = controller.Index(person.Id) as ViewResult;
// Assert.
Assert.NotNull(result);
var model = result.Model as VMPerson;
Assert.NotNull(model);
Assert.Equal(1, model.Person.Id);
Assert.Equal("John", model.Person.Username);
// Make sure we actually called the GetAll<Person>() method on our mock.
mockRepository.Verify(x => x.GetAll<Person>(), Times.Once());
}
}
Ok, lets look at what I did.
First, I arrange my crap. I first create a mock of the ILESRepository.
Then i say: If anyone ever calls the GetAll<Person>() method, well .. don't -really- hit a database or a file or whatever .. just return a list of people, which created in FakePeople.GetSomeFakePeople().
So this is what would happen in the controller ...
var model = _repository.GetAll<Person>()
.FirstOrDefault(x => x.Id == id);
First, we ask our mock to hit the GetAll<Person>() method. I just 'set it up' to return a list of people .. so then we have a list of 3 Person objects. Next, we then call a FirstOrDefault(...) on this list of 3 Person objects .. which returns the single object or null, depending on what the value of id is.
Tada! That's the money shot :)
Now back to the rest of the unit test.
We Act and then we Assert. Nothing hard there.
For bonus points, I verify that we've actually called the GetAll<Person>() method, on the mock .. inside the Controller's Index method. This is a safety call to make sure our controller logic (we're testing for) was done right.
Sometimes, you might want to check for bad scenario's, like a person passed in bad data. This means you might never ever get to the mock methods (which is correct) so you verify that they were never called.
Ok - questions, class?
Even when you do not plan to mock an interface, I strongly suggest you to do not hide the real dependencies of an object by creating the objects inside the constructor, you are breaking the Single Responsibility principle and you are writing un-testable code.
The most important thing to consider when writing tests is: "There is no magic key to write tests". There are a lot of tools out there to help you write tests but the real effort should be put in writing testable code rather than trying to hack our existing code to write a test which usually ends up being an integration test instead of a unit-test.
Creating a new object inside a constructor is one of the first big signals that your code is not testable.
These links helped me a lot when I was making the transition to start writing tests and let me tell you that after you start, that will become a natural part of your daily work and you will love the benefits of writing tests I can not picture myself writing code without tests anymore
Clean code guide (used in Google): http://misko.hevery.com/code-reviewers-guide/
To get more information read the following:
http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/
and watch this video cast from Misko Hevery
http://www.youtube.com/watch?v=wEhu57pih5w&feature=player_embedded
Edited:
This article from Martin Fowler explain the difference between a Classical and a Mockist TDD approach
http://martinfowler.com/articles/mocksArentStubs.html
As a summary:
Classic TDD approach: This implies to test everything you can without creating substitutes or doubles (mocks, stubs, dummies) with the exception of external services like web services or databases. The Classical testers use doubles for the external services only
Benefits: When you test you are actually testing the wiring logic of your application and the logic itself (not in isolation)
Cons: If an error occurs you will see potentially hundreds of tests failing and it will be hard to find the code responsible
Mockist TDD approach: People following the Mockist approach will test in isolation all the code because they will create doubles for every dependency
Benefits: You are testing in isolation each part of your application. If an error occurs, you know exactly where it occurred because just a few tests will fail, ideally only one
Cons: Well you have to double all your dependencies which makes tests a little bit harder but you can use tools like AutoFixture to create doubles for the dependencies automatically
This is another great article about writing testable code
http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html
There are some downsides.
First, when you have a test that depends on an external component (like a live database), that test is no longer really predictable. It can fail for any number of reasons - a network outage, a changed password on the database account, missing some DLLs, etc. So when your test suddenly fails, you cannot be immediately sure where the flaw is. Is it a database problem? Some tricky bug in your class?
When you can immediately answer that question just by knowing which test failed, you have the enviable quality of defect localization.
Secondly, if there is a database problem, all your tests that depend on it will fail at once. This might not be so severe, since you can probably realize what the cause is, but I guarantee it will slow you down to examine each one. Widespread failures can mask real problems, because you don't want to look at the exception on each of 50 tests.
And I know you want to hear about factors besides the execution time, but that really does matter. You want to run your tests as frequently as possible, and a longer runtime discourages that.
I have two projects: one with 600+ tests that run in 10 seconds, one with 40+ tests that runs in 50 seconds (this project does actually talk to a database, on purpose). I run the faster test suite much more frequently while developing. Guess which one I find easier to work with?
All of that said, there is value in testing external components. Just not when you're unit-testing. Integration tests are more brittle, and slower. That makes them more expensive.
Accessing the database in unit tests has the following consequences:
Performance. Populating the database and accessing it is slow. The more tests you have, the longer the wait. If you used mocking your controller tests may run in a couple of milliseconds each, compared to seconds if it was using the database directly.
Complexity. For shared databases, you'll have to deal with concurrency issues where multiple agents are running tests against the same database. The database needs to be provisioned, structure needs to be created, data populated etc. It becomes rather complex.
Coverage. You mind find that some conditions are nearly impossible to test without mocking. Examples may include verifying what to do when the database times out. Or what to do if sending an email fails.
Maintenance. Changes to your database schema, especially if its frequent, will impact almost every test that uses the database. In the beginning when you have 10 tests it may not seem like much, but consider when you have 2000 tests. You may also find that changing business rules and adapting the tests to be more complex, as you'll have to modify the data populated in the database to verify the business rule.
You have to ask whether it is worth it for testing business rules. In most cases, the answer may be "no".
The approach I follow is:
Unit classes (controllers, service layers etc) by mocking out dependencies and simulating conditions that may occur (like database errors etc). These tests verify business logic and one aims to gain as much coverage of decision paths as possible. Use a tool like PEX to highlight any issues you never thought of. You'll be surprised how much robust (and resilient) your application would be after fixing some of the issues PEX highlights.
Write database tests to verify that the ORM I'm using works with the underlying database. You'll be surprised the issues EF and other ORM have with certain database engines (and versions). These tests are also useful to for tuning performance and reducing the amount of queries and data being sent to and from the database.
Write coded UI tests that automates the browser and verifies the system actually works. In this case I would populate the database before hand with some data. These tests simply automate the tests I would have done manually. The aim is to verify that critical pieces still work.
I have a page that has a status text label and a panel doing some DB query. since the query can take some time I am loading it using
add(new AjaxLazyLoadPanel("resultPanel")
{
#Override
public Component getLazyLoadComponent(String id) {
return new SearchResultPanel(id);
}
};
which works very well.
My question is how to update the status label which is outside of the resultPanel, to show the number of search results?
I was thinking along the lines of addComonent(target) but I don't have a target? am i off the track?
Well the SearchResultPanel might look like this:
public class SearchResultPanel extends Panel implements IHeaderContributor{
public SearchResultPanel(String id){
super(id);
....
}
public void renderHead(IHeaderResponse response){
response.renderOnDomReadyJavascript("alert('hello');");
}
}
Now when it is loaded it should throw out that javascript. Another way answered on stackoverflow previously (though I do not like it) is to use an AjaxSelfUpdatingTimerBehavior, which unless the javascript should be ran more then once I do not like, and still it is less elegant in my opinion.
Look here for their answer: Wicket: reload AjaxLazyLoadPanel automatically
You can always obtain the current request target using RequestCycle.get().getRequestTarget(), provided that there is an active request cycle, so in theory you could do that from your lazy-loaded component constructor, check if it is an Ajax target, and add the component if it is.
Another solution is to look at the source code of AjaxLazyLoadPanel and create your own component based on it. (It's really simple but as you can see if you look at the code, there's no way you can make it expose the request target. This isn't a very OO thing to do, but as all the important functionality is wrapped in the constructor, you have very little choice..
I would avoid having to tamper with Javascript, unless there's really no other way.
Happened to come across this post and I have something to add as well.
The AjaxLazyLoadPanel now has an overridable method called onComponentLoaded(Component, AjaxRequestTarget) which could also solve your problem.
I'm writing my code in Haxe. This is quite irrelevant to the question though, as long as you keep in mind that it's a high level language and compareable with Java, ActionScript, JavaScript, C#, etc. (I'm using pseudocode here).
I'm going to work on a big project and am busy preparing now. For this question I'll create a small scenario though: a simple application which has a Main class (this one is executed when the application launches) and a LoginScreen class (this is basically a class that loads a login screen so that the user can login).
Typically I guess this would look like the following:
Main constructor:
loginScreen = new LoginScreen()
loginScreen.load();
LoginScreen load():
niceBackground = loader.loadBitmap("somebg.png");
someButton = new gui.customButton();
someButton.onClick = buttonIsPressed;
LoginScreen buttonIsPressed():
socketConnection = new network.SocketConnection();
socketConnection.connect(host, ip);
socketConnection.write("login#auth#username#password");
socketConnection.onData = gotAuthConfirmation;
LoginScreen gotAuthConfirmation(response):
if response == "success" {
//login success.. continue
}
This simple scenario adds the following dependencies and downsides to our classes:
Main will not load without LoginScreen
LoginScreen will not load without the custom loader class
LoginScreen will not load without our custom button class
LoginScreen will not load without our custom SocketConnection class
SocketConnection (which will have to be accessed by a lot of different classes in the future) has been set inside LoginScreen now, which is actually quite irrelevant from it, apart from the fact that the LoginScreen requires a socket connection for the first time
To solve these problems, I have been suggested to do "Event-Driven-Programming", or loose coupling. As far as I understand, this basically means that one has to make classes independent from each other and then bind them together in separate binders.
So question 1: is my view on it true or false? Does one have to use binders?
I heard Aspect Oriented Programming could help here. Unfortunately Haxe does not support this configuration.
However, I do have access to an event library which basically allows me to create a signaller (public var loginPressedSignaller = new Signaller()), to fire a signaller (loginPressedSignaller.fire()) and to listen to a signalller (someClass.loginPressedSignaller.bind(doSomethingWhenLoginPressed)).
So, with little further investigation I figured this would change my previous setup to:
Main:
public var appLaunchedSignaller = new Signaller();
Main constructor:
appLaunchedSignaller.fire();
LoginScreen:
public var loginPressedSignaller = new Signaller();
LoginScreen load():
niceBackground = !!! Question 2: how do we use Event Driven Programming to load our background here, while not being dependent on the custom loader class !!!
someButton = !!! same as for niceBackground, but for the customButton class !!!
someButton.onClick = buttonIsPressed;
LoginScreen buttonIsPressed():
loginPressedSignaller.fire(username, pass);
LoginScreenAuthenticator:
public var loginSuccessSignaller = new Signaller();
public var loginFailSignaller = new Signaller();
LoginScreenAuthenticator auth(username, pass):
socketConnection = !!! how do we use a socket connection here, if we cannot call a custom socket connection class !!!
socketConnection.write("login#auth#username#password");
This code is not finished yet, eg. I still have to listen for the server response, but you probably understand where I am getting stuck.
Question 2: Does this new structure make any sense? how should I solve the problems above mentioned in the !!! delimiters?
Then I heard about binders. So maybe I need to create a binder for each class, to connect everything together. Something like this:
MainBinder:
feature = new Main();
LoginScreenBinder:
feature = new LoginScreen();
MainBinder.feature.appLaunchedSignaller.bind(feature.load);
niceBackgroundLoader = loader.loadBitmap;
someButtonClass = gui.customButton();
etc... hopefully you understand what I mean. This post is getting a bit long so I have to wrap it up a bit.
Question 3: does this make any sense? Doesn't this make things unnecessarily complex?
Also, in the above "Binders" I only had to use classes which are instantiated once, eg. a login screen. What if there are multiple instances of a class, eg. a Player Class in a game of chess.
well, concerning the how, I would point out my 5 commandments to you. :)
For this question only 3 are really important:
single responsibility (SRP)
interface segregation (ISP)
dependency inversion (DIP)
Starting off with SRP, you have to ask yourself the question: "What is the responsibility of class X?".
The login screen is responsible for presenting an interface to the user to fill in and submit his login data. Thus
it makes sense for it to depend on the button class, because it needs the button.
it makes no sense it does all the networking etc.
First of all, you let's abstract the login service:
interface ILoginService {
function login(user:String, pwd:String, onDone:LoginResult->Void):Void;
//Rather than using signalers and what-not, I'll just rely on haXe's support for functional style,
//which renders these cumbersome idioms from more classic languages quite obsolete.
}
enum Result<T> {//this is a generic enum to return results from basically any kind of actions, that may fail
Fail(error:Int, reason:String);
Success(user:T);
}
typedef LoginResult = Result<IUser>;//IUser basically represent an authenticated user
From the point of view of the Main class, the login screen looks like this:
interface ILoginInterface {
function show(inputHandler:String->String->Void):Void;
function hide():Void;
function error(reason:String):Void;
}
performing login:
var server:ILoginService = ... //where ever it comes from. I will say a word about that later
var login:ILoginInterface = ... //same thing as with the service
login.show(function (user, pwd):Void {
server.login(user, pwd, function (result) {
switch (result) {
case Fail(_, reason):
login.error(reason);
case Success(user):
login.hide();
//proceed with the resulting user
}
});
});//for the sake of conciseness I used an anonymous function but usually, you'd put a method here of course
Now ILoginService looks a little titchy. But to be honest, it does all it needs to do. Now it can effectively be implemented by a class Server, that encapsulates all networking in a single class, having a method for each of the N calls your actual server provides, but first of all, ISP suggests, that many client specific interfaces are better than one general purpose interface. For the same reason ILoginInterface is really kept to its bare minimum.
No matter, how these two are actually implemented, you will not need to change Main (unless of course the interface changes). This is DIP being applied. Main doesn't depend on the concrete implementation, only on a very concise abstraction.
Now let's have some implementations:
class LoginScreen implements ILoginInterface {
public function show(inputHandler:String->String->Void):Void {
//render the UI on the screen
//wait for the button to be clicked
//when done, call inputHandler with the input values from the respective fields
}
public function hide():Void {
//hide UI
}
public function error(reason:String):Void {
//display error message
}
public static function getInstance():LoginScreen {
//classical singleton instantiation
}
}
class Server implements ILoginService {
function new(host:String, port:Int) {
//init connection here for example
}
public static function getInstance():Server {
//classical singleton instantiation
}
public function login(user:String, pwd:String, onDone:LoginResult->Void) {
//issue login over the connection
//invoke the handler with the retrieved result
}
//... possibly other methods here, that are used by other classes
}
Ok, that was pretty straight forward, I suppose. But just for the fun of it, let's do something really idiotic:
class MailLogin implements ILoginInterface {
public function new(mail:String) {
//save address
}
public function show(inputHandler:String->String->Void):Void {
//print some sort of "waiting for authentication"-notification on screen
//send an email to the given address: "please respond with username:password"
//keep polling you mail server for a response, parse it and invoke the input handler
}
public function hide():Void {
//remove the "waiting for authentication"-notification
//send an email to the given address: "login successful"
}
public function error(reason:String):Void {
//send an email to the given address: "login failed. reason: [reason] please retry."
}
}
As pedestrian as this authentication may be, from the point of view of the Main class,
this doesn't change anything and thus will work just as well.
A more likely scenario is actually, that your login service is on another server (possibly an HTTP server), that makes the authentication, and in case of success creates a session on the actual app server. Design-wise, this could be reflected in two separate classes.
Now, let's talk about the "..." I left in Main. Well, I'm lazy, so I can tell you, in my code you are likely to see
var server:ILoginService = Server.getInstance();
var login:ILoginInterface = LoginScreen.getInstance();
Of course, this is far from being the clean way to do it. The truth is, it's the easiest way to go and the dependency is limited to one occurrence, that can later be removed through dependency injection.
Just as a simple example for an IoC-Container in haXe:
class Injector {
static var providers = new Hash < Void->Dynamic > ;
public static function setProvider<T>(type:Class<T>, provider:Void->T):Void {
var name = Type.getClassName(type);
if (providers.exists(name))
throw "duplicate provider for " + name;
else
providers.set(name, provider);
}
public static function get<T>(type:Class<T>):T {
var name = Type.getClassName(type);
return
if (providers.exists(name))
providers.get(name);
else
throw "no provider for " + name;
}
}
elegant usage (with using keyword):
using Injector;
//wherever you would like to wire it up:
ILoginService.setProvider(Server.getInstance);
ILoginInterface.setProvider(LoginScreen.getInstance);
//and in Main:
var server = ILoginService.get();
var login = ILoginInterface.get();
This way, you practically have no coupling between the individual classes.
As to the question how to pass events between the button and the login screen:
this is just a matter of taste and implementation.
The point of event driven programming is that both the source and the observer are only coupled in the sense,
that the source must be sending some sort of notification and the target must be able to handle it.
someButton.onClick = handler; basically does exactly that, but it's just so elegant and concise you don't make a fuzz about it.
someButton.onClick(handler); probably is a little better, since you can have multiple handlers, although this is rarely required of UI components. But in the end, if you want signalers, go with signalers.
Now when it comes to AOP, it is not the right approach in this situation. It's not a clever hack to wire up components between one another, but about dealing with cross-cutting concerns, such as adding a log, a history or even things as a persistence layer across a multitude of modules.
In general, try not to modularize or split the little parts of your application.
It is ok to have some spaghetti in your codebase, as long as
the spaghetti segments are well encapsulated
the spaghetti segments are small enough to be understood or otherwise refactored/rewritten in a reasonable amount of time, without breaking the app (which point no. 1 should guarantee)
Try rather to split the whole application into autonomous parts, which interact through concise interfaces. If a part grows too big, refactor it just the same way.
edit:
In response to Tom's questions:
that's a matter of taste. in some frameworks people go as far as using external configuration files, but that makes little sense with haXe, since you need to instruct the compiler to force compilation of the dependencies you inject at runtime. Setting up the dependency in your code, in a central file, is just as much work and far simpler. For more structure, you can split the app into "modules", each module having a loader class responsible for registering the implementations it provides. In your main file, you load the modules.
That depends. I tend to declare them in the package of the class depending on them and later on refactor them to an extra package in case they prove to be needed elsewhere. By using anonymous types, you can also completely decouple things, but you'll have a slight performance hit on platforms as flash9.
I wouldn't abstract the button and then inject an implementation through IoC, but feel free to do so. I would explicitely create it, because in the end, it's just a button. It has a style, a caption, screen position and size and fires click events. I think, this is unnecessary modularization, as pointed out above.
Stick to SRP. If you do, no class will grow unneccessarily big. The role of the Main class is to initialize the app. When done, it should pass control to a login controller, and when that controller acquires a user object, it can pass it on to the main controller of the actual app and so forth. I suggest you read a bit about behavioral patterns to get some ideas.
greetz
back2dos
First of all, I'm not familiar with Haxe at all. However, I would answer that what is described here sounds remarkably similar to how I've learned to do things in .NET, so it sounds to me like this is good practice.
In .NET, you have an "Event" that fires when a user clicks a button to do something (like logon) and then a method executes to "handle" the event.
There will always be code that describes what method is executed in one class when an event in another class is fired. It is not unnecessarily complex, it is necessarily complex. In the Visual Studio IDE, much of this code is hidden in "designer" files, so I don't see it on a regular basis, but if your IDE doesn't have this functionality, you've got to write the code yourself.
As for how this works with your custom loader class, I hope someone here can provide you an answer.
OK, having tried my first TDD attempt, it's time to reflect a little
and get some guidance, because it wasn't that successful for me.
The solution was partly being made with an existing framework, perhaps
making TDD less ideal. The part that seemed to give me the biggest
problem, was the interaction between the view and controller. I'll
give a few simple examples and hope that someone will tell me what I
can do better wrong.
Each view's interface inherits from a base interface, with these
members (there are more):
public interface IView
{
void ShowField(string fieldId)
void HideField(string fieldId)
void SetFieldVisibility(string fieldId, bool visible)
void DisableField(string fieldId)
void ShowValidationError(string fieldId)
...
}
The interface for a concrete view, would then add members for each
field like this
public interface IMyView : IView
{
string Name { get; set; }
string NameFieldID { get; }
...
}
What do you think of this? Is inheriting from a common interface a
good or bad idea?
One on the things that gave me trouble was, that first I used
ShowField and HideField and the found out I would rather use
SetFieldVisiblity. I didn't change the outcome of the method, but I
had to update my test, which I seem should be necessary. Is having
multiple methods doing the same thing, a bad thing? On one hand both
methods are handy for different cases, but they do clutter the
interface, making the interface more complex than it strictly have to be.
Would a design without a common interface be better? That would remove
the fieldID, I don't why, but I think the fieldID-thing smells, I
might be wrong.
I would only make the Show and Hide methods, when needed, that is if
they would be called by the controller. This would be a less generic
solution and require more code in the view, but the controller code
would be a bit more simple.
So a view interface might look like this:
public interface IMyView
{
void ShowName()
void HideName()
string Name { get; set; }
int Age { get; set; }
}
What do you want to test? Whether Show* will make an widget in the UI visible? What for?
My suggestion: Don't try to figure out if a framework is working correctly. It's a waste of time. The people who developed the framework should have done that, so you're duplicating their work.
Usually, you want to know if your code does the right thing. So if you want to know if you are calling the correct methods, create mockups:
public class SomeFrameworkMockup extends SomeFramework {
public boolean wasCalled;
public void methodToTest() {
wasCalled = true;
}
}
Build the UI using the mockups.
The second thing to test is whether your algorithms work. To do that, isolate them in simple helper objects where you can all every method easily and test them with various inputs.
Avoid the external framework during tests. It only confuses you. When you've built a working product, test that using your mouse. If you find any problems, get to the root of them and only then, start writing tests against the framework to make sure this bug doesn't appear again. But 90% of the time, these bugs will be in your code, too.
At the moment I don't really see the added value of the common interface.
I think a better solution would be to have some properties on the controller class: IsControlXYZVisible. You can then databind the visible property of the control to this property.
And your unit test will test the value of IsControlXYZVisible, which will be easier to acomplish.
I also don't understand why you say you had a bad experience with TDD. I think your application architecture needs more work.
Your question is a little bit obscure for me but the title itself calls for a link :
The Humble Dialog box
And when you ask if it(s bad to have two functions doing the same thing, I say "Yes it's bad".
If one is calling the other, what's the point of having two functions ?
If not, you have a code duplication, that is a bug waiting to sprout whenyou update one and not the other.
In fact there is a valid case where you have two nearly identical functions : one that check its arguments and one that does not but usually only one is public and the other private ...