Sep 27, 2011

Never store a HTML element in a variable

Store its ID instead.

Because if its HTML source is moved or replaced, the previous element is destroyed and the new element is created with the same ID.

Sep 19, 2011

Clearing cookies on Selenium

You will need to go to the specified domain in order to clear cookies related to that domain

Sep 16, 2011

Selenium Superbug (Clicking problem)

Today I have just found out that Selenium WebDriver won't click on anything that is not on the current view.

This problem occurs because my HTML is somehow strangely designed that it makes Firefox(and Selenium) miscalculates the position of a target button. (My guess is floating css causes it.)

Selenium always scroll to the button before the clicking happens.

This time the button is not even in Firefox's view.

The direct fix would be to redesign the HTML or fix Selenium or Firefox.

Well, I cannot do that. So what I have done is changing the stylesheet of the button before clicking in order to make it visible in the view, and revert it back later.

The css I have added is {position:fixed; left:0px; top:0px;}

Sep 11, 2011

Lesson learned: never use kind_of?

Always use respond_to?

I have found the problem when doing the integration test and invoke the function to process the notification queue.

Somehow, there are 2 processes doing this. So, the same class in a source file might refer to different classes (identical name, but different object_id).

This presents a problem to kind_of? because it will return false, even the inheritance is correct.

Strange enough, kind_of? is only wrong when you use it against its superclass. Therefore, I think instance_of? won't have this problem.

Sep 10, 2011

A procedure to migrate database

1. Backup the database file into .bak
2. Make a change on CayenneModeler, save the XML
3. Generate migration SQL
4. Start Java application (because the migration will be run automatically) OR run the migration explicitly.

Database-related technology for Java application

One of the crucial things to develop a system is to maintain the version of the database schema.

Rails has the built-in procedure, which makes the development painless.

I have been looking into an ORM framework together with a database migration framework.

H2, Cayenne with Flyway are chosen.

H2 is chosen because it supports standard SQL and it is embeddable, yet still a powerful database.

H2 can be run with a mixed mode inside your Java application. The mixed mode means that your Java application can access H2 natively, while other applications (e.g. Rails) can access H2 through TCP.

And it performs well with many concurrent connections. (This is a big win over SQLite.)

Flyway is chosen (over Liquibase) because it offers Java APIs. This means that I can run migration at every startup of the server. You can also run migration from command-line, while Liquibase offers only command-line tools.

The good thing is that Liquibase offers portable migration script because it uses XML instead of raw SQL. However, we do not switch database that often.

Cayenne is chosen over TopLink and Hibernate because of its simplicity. Cayenne offers a GUI tool to manipulate the schema and generate SQL migration (that can be saved and used by Flyway.

TopLink and Hibernate are too good and, of course, more complicated.

Performance is not considered here because there are not many clients (50 at most). Therefore, any normal ORM will be ok.

-----

I have just found one con. The Cayenne GUI tool cannot create indexes...

Sep 6, 2011

Selenium 2.0 dark secret has been unlocked

Never ever focus on the Firefox window, which is being tested with Selenium.

This is because it will mess up the events and some clicking, specifically <a> and <button>,will fail.

(I have done a solid experiment on it. I have tested 4 elements, span, anchor, button, and input[button]. Only anchor and button have the problem)

----------------

OMG, I have solved it.

By focusing and send_keys "\n", the clicking problem is gone !!

Please be aware that the clicking problem only occurs with the anchor tag, and this approach does not work with other tags.

Therefore, please use the below code:



YESSSSS!


--------------------

I have found a problem with <button> that contains a span inside. But I could not repeat the problem. So, I'll just make a note right here for future reference.

Watir on Rails

I have been using Selenium + Capybara for a week now. Somehow, the clicking on Selenium is super unstable. The test cases occasionally fail.

It is really strange because Watir also uses selenium webdriver. But anyway the problem has gone now.

I have decided to give Watir a try. Anyway, Watir does not have an easy way to integrate with Rails 3.

Therefore, I have decided to build a gem for that.

And I proudly present you my first gem:

watir-webdriver-rails

I'm so friggin' happy :D :D :D

The gem is hosted on Rubygems.org. Therefore, you can install gem through the normal way

Sep 5, 2011

Selenium sometimes does not click on anchor tag with onclick

I don't know why it does not perform the clicking.

This upsets me so much. I thought Selenium is stable.

Now I'm moving to watir-webdriver, which partially use selenium-webdriver. But it does not seem to have any problems.

According to a StackOverflow's answer, we should use fire_event('click') instead.

But Capybara does not support fire_event()..

---------------

I have tried fire_event() with Watir.

Here is the result:

It works with any element with the onclick attribute. But it does not work with <a href="http://www.google.com">.

---------------

I am getting to the bottom of this problem now.

If the link we click has no CSS class, then everything is ok even we switch to that Firefox and move mouse over it.

If the link has a CSS class, but the class has no :hover and no :active, then everything is still ok.

If the link has a CSS class, but the class has :hover but no :active, then everything is still ok.

If the link has a CSS class, but the class has :active but no :hover, then Selenium will fail to click on an anchor if you move mouse over Firefox being tested.

It is so strange....

Sep 4, 2011

Architectures for a multi-client system

The first architecture design for a multi-client system is to:
- Open 2 threads for a single connection to client (One for reading, and another for writing)
- When a job come in, we fork a thread to do some jobs.

The problem with this architecture is that if there are 2 jobs that should not be done concurrently, then there is a big problem.

We can use the synchronized statement, but the synchronized statement cannot guarantee the order of jobs.

An example from POS system that breaks this architecture is when a client opens a table and the very same client make orders immediately after.

There is a chance that the make-order job will be processed before the open-table job.

----------------

The second design is:
- Open a single thread for a single connection. Therefore, this implies that when a request is sent, it expects a result. (Because there is only one thread for read and write.
- We use that same thread to process a job (since it has to give back the response anyway.)

This one is the current architecture. The jobs are nicely put in order.

But it loses performance in some cases.

The example that breaks it is when I open table 5 and make orders on it, then I open table 6.

It turns out that the open-table-6 request has to wait because the requests must be executed in order.

And there is a performance penalty when pushing an update. Because it has to wait until there is no request to be processed, then the thread will be available for writing update to the client.

-------------------

The third architecture is superior to those two.

- There are 2 threads to read and write socket. The thread of reading socket also translate request and add job to the queue.
- Queue is divided into multiple queue. Ideally, one queue for one table. This way we can ensure the order of execution.
- A job is dequeued by a worker. When a worker finishes, it posts a response to the writing thread.

With this design, everything is asynchronous. This means that each message must be labelled with a number. Otherwise, when we post a response, we won't know which request the response belongs to.

The implementation is a little bit harder though, but the abstractions are the same. We just process jobs differently. Therefore, it is just difficult on the architecture level, not the code itself.

I think this justifies the third architecture. We cannot just discard this architecture because it is difficult to implement...

Benchmark on the synchronized statement - Java



Here is the result:



It is somewhat strange that ratio for 100,000 loops is bigger than for 1,000,000 loops. Maybe JVM optimizes something for us.

Now if you are going to design a system with the synchronized statement, please beware of the performance detriment.

If you do not call the synchronized more than 10,000 times (within a minute), I would just use the statement and go with a simpler architecture design.

Sep 1, 2011

Groovy vs. JRuby

From what I have been researching, there is only one crucial difference between the 2 languages.

JRuby imposes no type on variables. This makes it extremely difficult to use Java's library because you will have an headache with overloaded methods and classes with generic types.

Groovy has type as an option. You can choose to have a type or not. With this, you can easily use Java's library.

And another thing to mention is that if you dream about using JRuby on Rails, then you should stop now. Many gems are written in C, which is impossible to use them with JRuby.

So think carefully before using JRuby because you would have to reinvent many wheels.

If you edit spec_helper.rb, please restart Spork

Otherwise all your test cases will have the error, StackOverflow.