Wednesday, 19 January 2011

UI Tests Automation for Silverlight

I'm currently working on a UI test automation task for Silverlight interface. There are not many tools available for that so we decided to evaluate the most popular one i.e. Telerik's WebUI Test Studio. I chose Developer Edition as it easily integrates with Visual Studio. For testers, managers etc there is also a standalone version available.

After a few days of playing with it I can already say it's quite powerful. Once you get familiar with it and learn a few tricks you can easily develop complex UI tests that would save your team a lot of time. Below is a short summary of its pros & cons:

Pros:
  • Supports Silverlight testing

  • Intuitive test recorder

  • For basic tests no coding required (also including logic: if/else, loops)

  • Integrated data access (spreadsheets, csv, database, ...) for data driven tests

  • Multiple video tutorials available

  • Full integration with Telerik's RAD controls

  • Strong community

  • Fast support

Cons:
  • Documentation doesn't cover the entire functionality

  • More complex tests require more coding than recording

  • Support for Silverlight available but yet limited (some additional coding required e.g. when veryfing the content of a ComboBox)

  • Dev & QA Editions differ slightly in available functionality (although I'm not sure that's really a con)

All in all, I would recommend it. I don't think there is really an alternative on the market. Is there?

Thursday, 4 November 2010

Visual Studio: Adding and using resource files

Sometimes you may want to include some existing files in your Visual Studio Project as project resources e.g. some text files that you would like to read from. This makes much easier to read their content from your code without manually working with streams etc. You can do that by following a few simple steps:
  1. Open Resource editor
    To do that right click on your project and choose "Properties" option. When the properties screen opens choose "Resources" tab: Visual Studio: Project Reources TabIf you haven't defined any resources before you'll be asked if you'd like to create a default Resource file for that project: "This project does not contain a default resource file. Click here to create one".

  2. Creat resource file
    When you confirm to do that the default resource file is created (see file marked on picture below) you can now choose to add a new file as resource: Visual Studio: Adding file as resource

  3. Add file as resource
    After you select the file it's available as resource. In my sample project I selected text file "test.txt". It also appeared in solution explorer (marked with red): Visual Studio: File declared as resource

  4. Access file content from code
    After you save all the changes you made to resources you can access the file content from your code simply by using its name:
    using SampleProject.Properties;
    ...
    string fileContent = Resources.test;

    You have to admit it's much easier then manually opening and reading from files.

Monday, 18 October 2010

The report server has encountered a configuration error. (rsServerConfigurationError)

After installing Sql Server 2008 with Reporting Services on Windows XP I needed to do some initial configuration to make it work locally:
  1. Open Configuration Manager
    Go to: Microsoft Sql Server 2008 > Configuration Tools > Reporting Services Configuration Manager

  2. Configure Web Service Url
    I used the default values suggested by configuration manager. To do that simply choose 'Apply'. Result: Reporting Services Configuration Manager - Web Service Url

  3. Configure Report Manager Url
    Again, I used the default values:


    Reporting Services Configuration Manager - Report Manager Url

After doing that I tried to to access: http://localhost/Reports
In my case I got displayed the following error:
The report server has encountered a configuration error. (rsServerConfigurationError).
To get rid of this I needed to perform to 2 extra steps:
  1. Define database to use
    I created a new database for Reporting Services using the same configuration manager:


    Reporting Services Configuration Manager - Database
  2. Set folder security
    Now check which account is used by reporting services:

    Reporting Services Configuration Manager - Account...and grant access for that user to the Reporting Services installation folder. In my case it is:
    C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services
After doing that I can access my Report Manager with no problems.

Wednesday, 6 October 2010

WCF Endpoint ABC

AS you probably know WCF stands for Windows Communication Foundation. If you want to make your WCF service accessible by clients you need to define at least one endpoint that would be used for communication. Each endpoint definition needs to answer 3 basic questions:
  1. Where?
  2. What?
  3. How?
To properly answer these 3 questions you need to specify so called "Endpoint ABC":

  • A - Address (Where?)
    This is the network address of your service saying where to find it. WCF support several address types/protocols. E.g. if you are creating a regular SOAP web service you would use an HTTP or HTTPS address. The type of the address depends directly on the binding type (see next definition).

  • B - Binding (How?)
    Binding defines how clients can communicate with our service. It specifies the transport protocol that should be used (HTTP, TCP, ...), web service protocol, encoding, security settins etc.

  • C - Contract (What?)
    Contract defines what functionality your service exposes. This is simply the interface that your WCF service implements.
In practice this could look as follows (SOAP web service endpoint):
Simple as ABC, isn't it? :)

Friday, 24 September 2010

Javascript parseInt() gotcha

Recently I was working on JS code that should convert strings (2 chars) into numbers from range 0-9 as presented below:

'00' => 0
'01' => 1
'02' => 2
'03' => 3
'04' => 4
'05' => 5
'06' => 6
'07' => 7
'08' => 8
'09' => 9

I used parseInt() function to achieve that. I was surprised to discover that the variables values where a bit different than I expected:
var i = parseInt('00'); // i = 0
i = parseInt('01'); // i = 1
i = parseInt('02'); // i = 2
i = parseInt('03'); // i = 3
i = parseInt('04'); // i = 4
i = parseInt('05'); // i = 5
i = parseInt('06'); // i = 6
i = parseInt('07'); // i = 7
i = parseInt('08'); // i = 0
i = parseInt('09'); // i = 0

Solution
As you can see parseInt('08') and parseInt('09') returned 0. This is because this function treats strings beginning with '0' as octal numbers and strings beginning with '0x' as hexadecimal numbers. To fix that you can provide the radix to use as a second parameter (optional):

var i = parseInt('00', 10); // i = 0
i = parseInt('01', 10); // i = 1
i = parseInt('02', 10); // i = 2
i = parseInt('03', 10); // i = 3
i = parseInt('04', 10); // i = 4
i = parseInt('05', 10); // i = 5
i = parseInt('06', 10); // i = 6
i = parseInt('07', 10); // i = 7
i = parseInt('08', 10); // i = 8
i = parseInt('09', 10); // i = 9

Monday, 30 August 2010

Multilingual database design approaches

A while ago I needed to create a database that would support storing data in multiple languages e.g. translated product descriptions for customer from different countries. When I started wondering how to reflect this in database schema it came out the answer is not straightforward. While searching Web for the one-and-only best practice i stumbled upon many opinions and approaches. Here are some most popular ones:

  1. Additional columns
    This is the simplest one, it's basically about creating an additional column for each text that needs to be translated e.g.
    CREATE TABLE app_product (
    Id Int IDENTITY NOT NULL,
    Description_en Text,
    Description_pl Text,
    PRIMARY KEY (Id)
    );


    Advantages:
    + simplicity
    + easy querying (no joins required)

    Disadvantages:
    - adding new language support requires schema changes for each table with multilingual content
    - if not all translations are required (e.g. at some places default language should always be used) it may cause redundant data or empty db fields.
    - hard to maintain

  2. Single translations table

    Approach with single translation table seems to be the cleanest one from database structure perspective. You store all texts that need to be translated in a single translation table:
    CREATE TABLE ref_language (
    Code Char(2)NOT NULL,
    Name Varchar(20) NOT NULL,
    PRIMARY KEY (Code)
    );

    CREATE TABLE app_translation (
    Id Int IDENTITY NOT NULL,
    PRIMARY KEY (Id)
    );

    CREATE TABLE app_translation_entry (
    TranslationId Int NOT NULL,
    LanguageCode Char(2) NOT NULL,
    Text Text NOT NULL,
    FOREIGN KEY (TranslationId) REFERENCES app_translation(Id),
    FOREIGN KEY (LanguageCode) REFERENCES ref_language(Code)
    );

    CREATE TABLE app_product (
    Id Int IDENTITY NOT NULL,
    Description Int NOT NULL,
    PRIMARY KEY (Id),
    FOREIGN KEY (Description) REFERENCES app_translation(Id)
    );


    Advantages:
    + adding new languages doesn't require schema changes
    + seems like clean, relational approach
    + all translations in one place (some may say it's a disadvantage because less readable/maintainable)

    Disadvantages:
    - complex querying (multiple joins required to retrieve correct product description)
    - overcomplicated

  3. Additional translation table for each table with multilingual content

    For each table that stores information that may need to be translated an additional table is created. The original table stores only language insensitive data and the new one all translated info:
    CREATE TABLE ref_language (
    Code Char(2)NOT NULL,
    Name Varchar(20) NOT NULL,
    PRIMARY KEY (Code)
    );

    CREATE TABLE app_product (
    Id Int IDENTITY NOT NULL,
    PRIMARY KEY (Id)
    );

    CREATE TABLE app_product_translation (
    ProductId Int NOT NULL,
    LanguageCode Char(2) NOT NULL,
    Description Text NOT NULL,
    FOREIGN KEY (ProductId) REFERENCES app_product(Id),
    FOREIGN KEY (LanguageCode) REFERENCES ref_language(Code)
    );


    Advantages:
    + adding new languages doesn't require schema changes
    + relatively simple querying (1 join required)

    Disadvantages:
    - may double the amount of tables

The 3 examples presented above give us an idea how different approaches may be used here. These are of course not all possible options, just the most popular ones. You can always modify them e.g. by introducing some additional views that would save you writing complex joins direct from your code.
The solution you choose depends mostly on your project requirements. If you need simplicity and are sure that the number of supported languages is small and fixed you could go with option 1. If you require bit more flexibility and can afford a simple join when querying for multilingual data option 3 would be a possible solution.

Friday, 27 August 2010

Using custom fonts on your website

Sometimes you want to make your website look better by changing fonts of some elements e.g. headings. When you set element's font you should choose one of so-called 'web safe fonts'. Web safe fonts are the ones that are by default installed on most of the computers, regardless operating system e.g. Arial, Verdana, Times New Roman etc. To increase the chances that the content of your website is displayed to each visitor using fonts you chose you can specify more than one font in your CSS:

.someclass {
font-family: Arial, Verdana;
}
In this case if the first font is not installed on client's machine the next one will be used.

Custom fonts
In some cases you may need to use a custom font that is most likely not installed on most of the client machines. Common example for such situation is when you receive a design from your client who insists you implement their website exactly like it was designed.

One of possible solutions would be using graphics for all page elements that were designed to use custom fonts. Disadvantages of this approach are:
  • This is not SEO friendly
  • Not suitable for dynamic text
The other option is to place the the font file on your webserver and using CSS point the browser to the font location:

@font-face {
font-family: custom_font;

/* for IE */
src: url(fonts/custom_font.eot);

/* non-IE */
src: local("Unique font name"), url(fonts/custom_font.ttf) format("truetype");
}

/* now you can use your custom font like any other */
.someclass {
font-family: custom_font;
}
Please not that browser needs to download the font first so it may slow down initial loading of your page. For IE you'll need the .eot version of the font. You can convert your ttf font into eot using this free converter. Each browser should only download one of the files.

If possible always try to use web safe fonts which can also produce great results.