CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Ranjan Sakalley

  • Writing unit tests for Windows Forms to test DataBinding

    Me and my pair were creating a form for the application, and basically testing out the data binding on the controls in the form.  Having  been bound to a domain object, the controls were tested as -

    1. Create a domain object, and set the properties to be bound with random values.

    2. Bind this/empty domain object to the windows form controls.

    3. Set/Change the values in the controls(like Text property of a TextBox, depending on this being a create or edit form.

    4. Assert the values of the current domain object state, with the values set/edited for equality.

    Our library, to perform step 3, consists of methods like the following -

      void SetControlValue(string name, string controlProperty, object value);

    which find out the control, then find out the mentioned property using reflection, and then set that property to the "value".

    As we started writing the first test to check up the state of the first control, we found a major issue. Even after the 4 steps, the asserts were failing. We spent around 2-3 hours trying to find out if the data binding was done correctly or not, or if the repository methods that were setting the control values using reflection were doing it correctly. Just as we got up to ask for help, one of our collegues mentioned that -- A control's DataBinding does not update the values in the object bound to it until the focus on the control changes.

    Why did I not notice it before writing my first test case? Having never written a unit test on any Windows Form, I was used to test my control bindings by checking the saved values etc. And that happened on the click of the "Save" button, which means the focus changed from the control to the button, and the data was saved to the object, and I could never notice this.

    Man its fun to write tests.

    Technorati :
    Technorati Profile
    Posted Apr 16 2006, 04:23 PM by rsakalley with 3 comment(s)
    Filed under:
  • Dialog Units

    Microsoft recommends a left margin of 7 Dialog Units (DLUs) (here) between controls in forms. So what is this DLU?
    The definition follows -
     A vertical dialog unit equals 1/8 the font height, and a horizontal dialog unit equals 1/4 the font width.

    The actual problem is,  when we talk about the system font above, how do we design a form, for a variety of possible font sizes and system resolutions, on the dev machine? Should we keep the measurements dynamic or is there a way to mandate the sizes in DLUs, rather than pixels?



    Posted Apr 11 2006, 05:35 AM by rsakalley with 4 comment(s)
    Filed under:
  • New job

    I joined ThoughtWorks as an application developer. It was a wonderful day, had a real nice time talking to some of the people there. Incidentally, Martin Fowler is in the India office these day, so maybe I will get to meet him sometime.

    BTW, moving from Outlook 2003 to Lotus Notes is a hell of an experience. Embarrassing at times.
    Posted Apr 10 2006, 03:13 PM by rsakalley with 1 comment(s)
    Filed under:
  • Some VS2005b2 likes and dislikes

    Likes -

    Clean Solution/Project

        Helps out to clean the solution/project output. Cleans out Copy Local assemblies, as well as the compilation output of the project.

    Reference properties - specific version (true/false)

        Very useful if different developer machines have different versions of components (though extremely dangerous if you have not rule out the use of conflicting methods).

    Framework for private method testing

        The framework gets generated as soon as you "Create Tests" for a provate function. Neat pattern used.
            

    Dislikes -


    No default Shortcuts

             No default shortcuts for TestView (though you can go to Tools > Keyboard and add this one), to run a particular test, as in TestDriven.Net plugin, which I have got used to.

        No option to add shortcuts too. Because the IDE does not identify a unit test at design time, just after right-clicking over a part of the Unit test, I dont think there is a VS IDE function, that can be given a shortcut. This is really sad. 
       
            Having used ReSharper for some time now for VS2003, it has become cumbersome to move over from the Eclipse style refactoring to the Ctrl K key set. Not that I want Whidbey to copy them, but because there are less number of refactoring options, it *might* be a better idea to upgrade ReSharper's subscription.

    Anyway, its just Beta2, so we still have time to force a solution to the Keyboard ignorance issue.

    Posted Jul 18 2005, 04:39 PM by rsakalley with 3 comment(s)
    Filed under:
  • Requirements collection for User Interfaces

    End users interact with your software only through the User Interface, and therefore, you must understand that for them the User Interface is the software. Architects, and developers in general forget this, and are predominently concentrating on design patterns, antipatterns, language nuances, tiering and layering, data communication between machines etc. throughout the software development life cycle. Whilst the above mentioned entities are essential towards a good product, User Interface is the most important of all the aspects of a software; this, if you are in the business of selling the software, or providing an end user a convenient solution. Many a time, I forget the actual motive behind writing a software, which invariably is improvement in productivity of the users of the software. User interface forms a very important part of what we are writing the software for. This is the reason why people took Windows over Unix a long time back.

    Essentials for an effective user interface
    An effective user interface helps a user perform a task with the minimum possible effort. To create one, you must understand the user, just like a motion picture director understands the audience, and manipulates their feelings. Following are some aspects of the audience that you must know, before starting to design an effective user interface -

    Individual Technical ability
    Gather information on the computer literacy of the users. Instead of letting them tell you about it, start with a set of questions first, get these questions answered by all possible end users, or if you are developing a product, a trusted sample target audience. I would normally ask atleast the following -

    General questions - questions that would give us some metrics on what is the technical ability of the users
    • Do you like working with machines? Computers?
    • What is your current position in the company, does it involve working with computers?
    • Have you undergone a formal computer training program?
    • Do you think a computer can add/has added to your productivity?
    • Do you have a computer back home?
    • How often do you use a computer? How much time do you spend every day?
    • Please rate yourself from 1-10 on your typing speed/skills?
    • How would you like to classify yourself, as a mouse-user or a keyboard-user?
    • Are you left handed? If yes, do you use a left-handed mouse?
    • What are the the problems you have faced, and currently face when you are working with a computer?
    • Do you like a colourful interface to the software, or a simple classy one?
    • Do you like reading articles on the computer? Do you increase the font sizes when you are reading?
    • Do you feel comfortable with simple menu items with small images, of you would prefer an interface with big image buttons on the screen?
    • Do you get bored of the user interfaces that you use currently? Tell us what actually do you feel is the reason behind it.
    • How often do you use software help manuals, per day?
    • How would you react to a new software given to you?
    • How much time would you prefer to spend on getting trained? Do you think the training time has its worths?

    Once you get the answers to such questions, get some metrics out of them, form small groups of people who you can classify as
    a. People who got bored answering because they know too much.
    b. People who answered the questions positively.
    c. People who answered the questions correctly, and gave you a good picture of what they are looking for.
    d. People who got bored answering because they did not know what you were asking about.
    and many others. If you cannot talk to all of these, find atleast two median users of each such class, and talk to them regarding how they feel about Computer software in general, and what are their basic needs and problems with computer interaction.

    With these questions, you would have a definitive picture about the knowledge, enthusiasm levels and a little information on technical capability of the users, the stress you need to put on keyboard shortcuts and tab-orders etc., the problems that you need to solve for them, specifically in terms of their past experience with user interfaces, and some other questions like would you need to support skins etc. These questions would sometimes give you a picture of what the users expect in terms of Help manuals and training too. A set of 20-30 such questions would really help you getting this knowledge.


    Group technical capabilities - User classifications in the Enterprise scenario
    With a result set of the questions above, you would actually be able to classify users with their job functions in the target organization. I mention this, because most enterprise automation software involve a lot of roles, each separated by the other based on education, aptitude and talent etc. of the employee. And for each such role, their is a separate user interface that you need to design. With the metrics from the last questionnaire, and after the meetings, you might be able to define the traits of each role. Following is a set of roles that you might get, with a healthcare provider organization -

    System Administrators - highly efficient computer users, very enthusiastic in controlling all aspects of your software.

    Nurses - least efficient but highly enthusiastic. Might not know what they want, and hence you have to pitch in extra effort.

    Doctors - normal efficiency, but would like the software to do and be everything, "no clicks" requirements

    Clerks - very efficient, understand computers and have specific requirements. Reporting needs.

    Data entry personnel - good typing skills, keyboard freaks, require perfect data flow.

    Marketing managers - not good with computers as such, but want to use them, requirements run around communications and almost everything you can write reports on.

    Human resource managers - undertand the importance of keeping records, generally require reporting and file storage capabilities.

    Receptionists - efficient typists, prefer a POS like user interface.

    Lab managers - record keeping, communication and integration requirements.

    and so on.

    Divding the audience, into small identifiable groups is one of the best ways to go ahead with user intefraces. It helps in putting concentrated efforts on each module of the UI, right from the time when you start writing proof of concepts. Once you can group the users as a set, and have clear boundaries of each role, you have to start preparing questions for each such role, asking questions designed specifically on their tasks, and how they want the user interface for each task to look like. I am currently reading a book on Paper Prototyping, and its definitely a way to go.

    As a conclusion, I would mention that each end user is unique, and to strive to satisfy every one of the end users is a noble task. One needs to understand the limits to which such customizability can be provided, and these limits cannot be drawn without gathering a comprehensive set of metrics. Whether you go ahead with satisfying each user, or by grouping end users into roles, and then satisying the median of such roles, you must first understand the importance of the User Interface, and then their requirements.









  • Product design and integration

    A few days, a colleague posted some insights on Design Principles here (http://www.proteans.com/CS/Web/blogs/agilerup/archive/2005/07/06/18.aspx). There were very interesting topics, discussed briefly, and one of them was about the emphasis one should have, when designing, on integration. I have had some thoughts on the same too, and here they are, following a little background information.

    What is integration? And where does it come into picture?

     Suppose you create a great accounting package, for SMEs. Its very good, got good performance, great UI, the clerks love it, the ladies go nuts over it, if looks could kill and all that, you know. Now we understand that this is not a killer app, because there are many accounting packages out there in the market, many from big and dependable corporations like MicroSoft, many well established like Quickbooks, and many much simpler than yours. But you have a great Sales and Marketing team that really toils hard, and sells a thousand copies. You will now, definitely face one of the following scenarios, if not all of them -

     1. You Sales and Marketing girl comes back and tells you that most of the people that she talks to about our product, say that they want an accounting package which can take in inputs from their web-site too. Ours doesn’t support that, so they don't even talk about it any further. Then there are people (Prospects) who have some partners out there in business, providers of raw-materials etc., and the partners have, let’s say, QuickBooks installed on their site, and the prospects want to get rid of paperwork, and want the accounting package they buy, to talk directly to their partners' package. So these guys don't talk to the poor (well yes, there are such rare situations, where you can use the word poor as an adjective for Sales people) lady, and she is now getting red at you, for not thinking of such situations when designing the package.

    2.  You identify a liquor store as a major prospect, you visit them personally, try to impress them with your tech-talk and all. But they counter everything with some of their own. You tell them about your package, and they start asking you about how your package would work with their existing infrastructure. They start talking about ESBs, BizTalk and all, and you take your sad face home, thinking what went wrong, where are good old stupid liquor store managers going these days.

    3. One of your clients grows really fast, and is generally happy about the software that you gave him. But now, he needs an Inventory Management solution too. So he buys one, but later finds out that instead of improving his inventory management, installing this new software has increased the paper-work, and along with it, chaos in the office and his staff productivity has decreased to half. He digs deep to find out that this is because of the technical incompatibility between the accounting package you wrote, and the inventory management software he bought. He is in an indecision mode, and during this period, the company that sold him the inventory management software calls him up, and tells him about the new accounting package they are writing, which seamlessly(the regular sales talk, you know) integrates with their other softwares. The client calls to tell you his decision, for him the decision is great, but for you? The story doesn't end here, this guy goes and posts a recommendation on a web-site, and now the number of distracted clients is really growing, and your business is going down. Would a new version really help in this scenario?

    In any case, with almost all enterprise products, and even some standalone ones, you would encounter such cases. This is why software’s ability to provide an integration API, or its ability to seamlessly become a part of an integrated infrastructure of products is important, it’s the need of the hour, and it’s this integration-ready software which would sell. This is the main reason for major players chiming SOA mantras in every major event, on every technical website.

    How do you go about the design decision?

    Following are three good ways to find out about how you should actually go ahead.

    1. If you are in the process of designing an enterprise level solution or for that matter any other solution, research the market to find out the prospect users. Talk to them, before designing the product, and not after the development is done. Ask them about what issue they have faced with paperwork between different departments. Ask them if they are looking for software that does not require manual intervention for communication of data between the software their other departments use. Next, ask your prospect customers what kind of "other" software would they like your software to work with. In other words, research on the environment in which your software would be deployed.

    2. If you already have a partner in the market, who complements your line of products with its own, ask them if they want their products to synergize with yours. Ask them what their software would need to "talk" to yours. Find out what would your software need to "talk" to theirs.

    3. Do you want to improve your future business, by providing APIs/Platforms for integration today? When you grow with an accounting package (for example), do you want to write and sell an inventory management system that talks to the latter? What happens when you write a shipping management system? In other words, does your vision extend to a scenario where this product you are writing is just the first in the line of a complete enterprise solution in future.

    If you have bought the idea of integration by now, you must start making decisions on implementation strategies for integration. I have borrowed some ideas, which you can easily extrapolate on.

     Implementation

     Now integration is definitely not anything new, and almost all enterprise software vendors have faced customer demands around it in the past. Some have solved it concentrating on the state storage system, some using messaging, and there are other ways too.

     Integration based on state storage systems

    This is a very fragile architecture, wherein when some data is changed in a software's domain, this software indicates other "integrated" software by either writing the data to a file or invoking a database trigger.

     Messaging

    Software sends messages to a sink, which other software read to update their data, according to the message. This is a very good and agile mechanism. Unfortunately, traditional messaging techniques are more or less platform or OS specific.

     XML based messaging and SOA

    This is an extension of the previous, but because of the use of XML, this makes it possible to integrate with a wide range of products. Morover, a good service oriented architecture enables other software systems to indicate data/state change to yours, and thus provides a way to complete integration. My team is freshly through the integration phase, where we integrated an EMR system, running on a Unix machine and exposing a Java web-service, with one of our client's .Net based medical transcription products. There are many ISVs that specialize on integration, some use Enterprise Service Bus(ESB) products (mostly Java), while Microsoft is taking integration forward with Biztalk.

     
    I would therefore strongly suggest SOA, if and when you decide on your integration strategy. And yes, don't forget to put that paragraph on why or why not you are considering integration, in your design document. Follow this up with a good strategy (if yes), based on strong market research. There are some good books and web-sites in the market for Enterprise Application Integration (EAI), EAI Patterns etc. which would definitely help you find out the correct integration strategy. Just open your eyes.

     

  • Friday Trivia

    • This was a poster put up in 1978 explaining something. Who put it up and what is being explained?

     

                                 * If it's there and you can see it--it's real

                                 * If it's not there and you can see it--it's virtual

                                 * If it's there and you can't see it--it's transparent

                                 * If it's not there and you can't see it—you erased it!

     

     

  • Definition of a "Wicked Problem"

    Off late I have been using this term a lot, since I read about it in a Stephen Covey book.

    A wicked problem is a problem that could only be defined by solving it, or part of it.

    I have been busy currently on a product that manages more than a GB of data transfer between servers and automates several workflows, and God knows how many wincked problems have been defined till now. And there are still many of them left to be solved.

    A simple example of a wicked problem that I am going to face is software performance. Wonder if you can share some?

  • Can TDD help managing and guiding off-shore teams?

    One of the first ideas that I had, when I started reading about TDD was this -

          Can a manager/lead keep track of the code written by his team, by inspecting and adding to the tests written by them?

    My experiments give me an affirmative. What about you?

    Also, I wonder if an off-shore team can be managed following this process, atleast in terms of development direction?



    Posted Jun 21 2005, 11:50 PM by rsakalley with 4 comment(s)
    Filed under:
  • On quality consciousness of Off-shore development organizations

    Sahil here mentioned the state of H1B holders in the US. Profounding statements, and nicely put. Must read. There is a reference that comes though in one of the praragraphs, about the state of mind, and the their life style in the US. There is no mention on the work-quality, which has come under much criticism, so I would like to add to, on that front.

    One of my observations, during a little bit of hiring here in India has been that Indian Software workers are above average earners in this country, and cities like Bangalore have a huge clout of these big-earners, and everybody's getting attracted to such places. Earlier, people used to get Rs 5000 (around $125) per month, and are now getting Rs 40k ($ 1000). The industry's like a honey pot and all including me are attracted.

    Everybody's looking for such jobs . People who don't have a good programming background, not even the talent to be analysts or developers are interested into becoming programmers (its another argument that you dont need talent to write code, but thats okay, I subscribe to that, but its private).

    That's just one face of the coin. There is a good number of Indian Services Providers, who charge very less, compared to their US of A counterparts, but in terms of dollar conversion to Rupees, they are still earning 10 times over the employees' salaries. And they want more. For a job that can be done by a 100 guys, they hire 400 (that's called the SEI CMM syndrome by us locals). And they hire and charge for these guys (which is called the Headcount formula), because they want to increase their revenues. To improve from 100 to 400, you need cheaply available guys, which are just around the corner.

    So that's one of the reasons. Cheap training and poor management (which are just the guys I talked about, promoted) are other reasons.

    But yes, there is more to it. Criticism apart. There are good companies, with really good staff, and visionaries on their board, who not only are looking at quality (which is much more that CMM levels, that they have, but they look for much more than that) but class people, who will make the organization proud when they move over to any off-shore location. These organizations hire smart people, attract smarter people, pay nice enough salaries, make their off-shore stays at the least as comfortable as home, and are honest, hire only the needed, morover they prove their mettle with their product. My vote goes to such organizations. I prefer not to name any one of such an organization, as I do not name any of the ones I criticized. I also would like you to comment on your organization, tell more about the kind of work-culture they have, share your experience. Personally I prefer to work for such organizations, and one day would like to build one such company.



     
  • How to resize the columns of the grid databound to an array at runtime?

    While working on the new product (and that's why the break) we got into a DataBinding situation. We had a DTO class, something like this

    public class Employee
           {
                  private string employeeName;
                  private string employeeId;

                  public string EmployeeName
                  {
                         get { return employeeName; }
                         set { employeeName = value; }
                  }

                  public string EmployeeId
                  {
                         get { return employeeId; }
                         set { employeeId = value; }
                  }

                  public Employee(string employeeName, string employeeId)
                  {
                         this.employeeName = employeeName;
                         this.employeeId = employeeId;
                  }
           }

    and to show the data on a DataGrid (System.Windows.Forms.DataGrid) we used an array of such an object as a DataSource to the grid. And then we got into a situation. How to resize the columns of the grid at runtime? Using TableStyles ? Would the following code work (this is the method written in the wrapper to the DataGrid and called on DataSourceChanged event)?

                  private void RedrawGrid()
                  {
                         if (this.DataSource == null || this.Width == 0)
                         {
                               return;
                         }

                         this.TableStyles.Clear();
                         Array dataSource = (this.DataSource as Array);
                         Type type = dataSource.GetValue(0).GetType();
                         //tableStyle.MappingName = type name or variable name?
                         DataGridTableStyle tableStyle = new DataGridTableStyle();
                         tableStyle.AlternatingBackColor = Color.GreenYellow;

                         foreach (PropertyInfo property in type.GetProperties())
                         {
                               DataGridTextBoxColumn columnStyle = new DataGridTextBoxColumn();
                               columnStyle.MappingName = property.Name;
                               columnStyle.Width = this.Width/this.VisibleColumnCount;
                               tableStyle.GridColumnStyles.Add(columnStyle);
                         }
                         this.TableStyles.Add(tableStyle);
                  }


    This is how you would do the stuff if the DataSource was a DataTable. Right? No, I missed the MappingName. Without this, the style won't be mapped to the Grid. So what do you normally set the MappingName to when you bind the grid to a DataSet/Table? answer: The TableName. Something like this

    //strictly if the source is a table, and here just for reference
    tableStyle.MappingName = (this.DataSource as DataTable).TableName;



    But what would you set it to, when it comes to an array? Does the same idea, that of the variable's name work here? Surprisingly NO

                        // Works
                         Array dataSource = (this.DataSource as Array);
                         Type type = dataSource.GetValue(0).GetType();
                         tableStyle.MappingName = type.Name + "[]"; //i.e. Employee[]
                         dataGrid.TableStyles.Add(tableStyle);


    In the case of a DataTable, the TableStyle is mapped to the TableName (that is, the name of a variable), while in this case, its named to the class's name (string "Employee[]"). not the base class's name (System.Array), not the fully qualified name ( Proteans.DataTransfer.Employee[], but just Employee[]. And yes, no guidelines from MSDN whatsoever?

    Anyway, it worked and I am happy. So for people who were searching for a way to have the runtime column resizing feature for a Datagrid bound to an Array, use the Array type as the mapping name, and define the ColumnStyles etc. then on. My 2 cents.




     






    Posted Jun 07 2005, 11:29 PM by rsakalley with 5 comment(s)
    Filed under:
  • TDD with Whidbey (Team Test)

    Honestly, its good to have a test generator right there in your own sweet copy of VS.Net. But you need to buy the Team Test edition of the Team System. Sad. In the past, I have argued with many people about generated test cases, from people who have written books on TDD to normal people like me, and all their arguments were centered on "You will lose the control"/"Whats the use of TDD then?"/"What about test first and code then?". Except for the last one, these are very much similar to the ones which came forward when people cried about why "Drag Drop"/"Visual Studio Generated code" for VB(of which i know nothing) and other languages (and this was my argument :) ) . Ofcourse every geeko will take their time criticizing this feature, embracing it later one way or the other. Paying for it too. Sad.

    Personally I hold the last point, namely "test code first and then code" to be the strongest argument out there against code generation. I have thought about this a lot, and though I understand that I am no high authority in this world, I find myself thinking that its just a philosophy. And as any other philosophy, there are better and more personalized ones out there. Which broadly means that as and when I find myself in a situation where generation speedens my development process, I shall use it, no matter what people say. Good old test first is correct, and it shall carry on, with a little personal twist on my side.

    Wait, I have one more argument! Most of the people think that TDD cases are just a way to verify the "correct"ness of the code, by developers. No. Not just that. TDD cases, i.e. code written to test code actually opens up a new perspective towards quality verification by third parties too namely the QA teams. They tally their use cases with the test cases, write extra if there are none there for the use-cases. They are not developers (which is sad, and they earn more than developers, which is sadder still) so they normally work on written code. What of them?

    So test generation is ok by me, because it serves a purpose. If handled correctly. Sad.
    Handle it correctly.

    Here is some insight I might provide. Darrell has already written about how to re-use your NUnit test cases ( I really wish MS had supported this rather than creating their own, with Mr.Newkirk right there in Redmond) here (http://codebetter.com/blogs/darrell.norton/archive/2004/06/17/16811.aspx).
    In brief, almost all attributes, asserts and static calls are supported. So you just need to change one "using" line. And so, I will try to concentrate on the generator.

    Lets take a class that needs to be tested.

    namespace Tested
    {
        public class Math
        {
            public int Add(int firstNumber, int secondNumber)
            {
                return firstNumber + secondNumber;
            }
        }

    }


    Generated test class for the Add method is-

    using Microsoft.VisualStudio.QualityTools.UnitTesting.Framework;

    // The following code was generated by Microsoft Test Code
    //  Generation V1.0. The test owner should check each test
    //  for validity.

    namespace Tested
    {
        ///
        /// This is a test class for Math and is intended
        /// to contain all Math Unit Tests
        ///
        [TestClass()]
        public class MathTest
        {
            ///
            /// Initialize() is called once during test execution before
            /// test methods in this test class are executed.
            ///
            [TestInitialize()]
            public void Initialize()
            {
                //  TODO: Add test initialization code
            }

            ///
            /// Cleanup() is called once during test execution after
            /// test methods in this class have executed unless
            /// this test class' Initialize() method throws an exception.
            ///
            [TestCleanup()]
            public void Cleanup()
            {
                //  TODO: Add test cleanup code
            }

            private TestContext m_testContext = null;

            public TestContext TestContext
            {
                get { return m_testContext; }
                set { m_testContext = value; }
            }

    ///
    /// AddTest is a test case for Add (int, int)
    ///
            [TestMethod()]
            public void AddTest()
            {
                Tested.Math target = new Tested.Math();

                //  TODO: Initialize to an appropriate value
                int firstNumber = 0;
                //  TODO: Initialize to an appropriate value
                int secondNumber = 0;

                int expected = 0;
                int actual;

                actual = target.Add(firstNumber, secondNumber);
                Assert.AreEqual(expected, actual);

                Assert.Inconclusive("Verify the correctness of this test method.");
            }

        }
    }

    Stop tinkering about my color coding scheme. I am color blind. Concentrate. We need to do this correctly.

    You can yet again read about the attributes at msdn2.microsoft.com (wait, there are no descriptions there, and may be that's why I am telling you to go there.) Let me try -

     [TestClass] = [TestFixture]
     [TestMethod]  = [Test]
     similarly [TestInitialize] [TestCleanup] are mapped to the corresponding SetUp and TearDown attributes. ( naming something differently does give you a copyright, am I right?).

    So the test case looks like -

            public void AddTest()
            {
                Tested.Math target = new Tested.Math();

                //  TODO: Initialize to an appropriate value
                int firstNumber = 0;
                //  TODO: Initialize to an appropriate value
                int secondNumber = 0;

                int expected = 0;
                int actual;

                actual = target.Add(firstNumber, secondNumber);
                Assert.AreEqual(expected, actual);

                Assert.Inconclusive("Verify the correctness of this test method.");
            }

    TODO's  are I think very nice, I need not run around trying to find out where to initialize to an appropriate value. I call it the VB touch.  "expected" and "actual" are pretty descriptive names. Then there is the regular assert. And then there is Inconclusive, which is basically there to notify you to write a conclusive test case (by commenting the line? ha)

    Anyway, what my point is (listen, its not very hard to understand), is that I fight all those people, tell everybody how good generating test cases would be, and all I get is ONE test case?

    Who will write the test cases to check the method input parameters?
    Who will write the test cases with expected exceptions?
    Where should I define my own test template, and then the generator generate the test cases based on that?

    Like you would have guessed, this test case generator is inconclusive. Its got nothing yet, and I hope it would be improved. Till then, I am happy to write my own test cases, and write them first. (Do look into the tests generated for the private methods. Really a great implementation.)

    Anyway, I am just one in more than a million, so the VS.Net team might not even notice this, and so......

    Lastly, I am not color blind. I am just lazy (as you would have guessed too, by now).

    Posted Apr 29 2005, 06:59 AM by rsakalley with 9 comment(s)
    Filed under:
  • Friday Quiz I : Who wrote the first Hello World program?

    Thought about starting a quiz series, a question every friday kind of. So todays question is :
    Who wrote the first "Hello World" program?

    I might know it, but I am not sure. Do you know?

    Posted Apr 28 2005, 10:37 PM by rsakalley with 6 comment(s)
    Filed under:
  • Loading two versions of an assembly that are not in the GAC

    Many a time you might face this issue. Especially when you are using a third party component, which uses an older version of an assembly, of which you are using a newer version. Pre 2.0 (and I do not know for sure of 2.0) compiler compliant to the CLS do not support the functionality of a static reference of two differently versioned assemblies with the same name at compile time.

    The safest way to do this is Load the assembly object at runtime using Assembly.Load and then calling the appropriate methods. Do not forget to give different display names to these. If the assemblies have strong names and they are Loaded then, they are treated as different assemblies by the CLR. If the assemblies are not strong names, even two identical assemblies loaded from different paths are considered two different assemblies. In both the cases (strongly named or not) even the identical types in the two assemblies are not castable to each other.  
    In other words, you have an Assembly X v1.0 with type A and type B. Type B changed with X v2.0 but type A did not. Even so, if you create an object of type A using the reference of Assembly X  v1.0, you will not be able to cast it to the identical Type A of the Assembly X v 2.0. So do not design your application in such a way that you need to cast types in two different assemblies. Or otherwise, include a casting provider.

    Code

    Lets say we have an assembly AssemblyX. Version 1.0.0.0 has the following classes

    public class A
                 {
                             public void WriteToConsole()
                             {
                                          Console.WriteLine(" Class A, AssemblyX version 1.0 " );
                             }
                 }

    public class B
    	{
    		public void WriteToConsole()
    		{
    			Console.WriteLine(" Class B, AssemblyX version 1.0 " );
    		}
    	}
    

            Version 2.0.0.0 of AssemblyX has the following classes

          
    public class A
    	{
    		public void WriteToConsole()
    		{
    			Console.WriteLine(" Class A, AssemblyX version 2.0 " );
    		}
    	}

     

    public class B
    	{
    		public void WriteToConsoleV2()
    		{
    			Console.WriteLine(" Class B, AssemblyX version 2.0 " );
    		}
    	}
    
    

     AssemblyX v1.0.0.0 is already added as a static reference to our project, lets call it AssemblyLoader (console application), directly or indirectly. Following is the code I have used to load the newer version too, along with the older one, in the same AppDomain,

    public class Loader
    	{
    		static void Main()
    		{
    			Loader _loader = new Loader();
    			_loader.LoadAndRunMethodsV1();
    			_loader.LoadAndRunMethodsV2();
    			_loader.TryCastA();
    
    			Console.ReadLine();
    		}
    
    		public void LoadAndRunMethodsV1()
    		{
    			AssemblyX.A _a = new A();
    			AssemblyX.B _b = new B();
    
    			_a.WriteToConsole();
    			_b.WriteToConsole();
    
    		}
    		public void LoadAndRunMethodsV2()
    		{
    			Assembly _assembly = 
    Assembly.LoadFrom(@"E:\Blog\Assemblies\v2\AssemblyX.dll"); Type Av2 = _assembly.GetType("AssemblyX.A"); Type Bv2 = _assembly.GetType("AssemblyX.B"); object _a = Activator.CreateInstance(Av2); object _b = Activator.CreateInstance(Bv2); MethodInfo _mA = Av2.GetMethod("WriteToConsole"); MethodInfo _mB = Bv2.GetMethod("WriteToConsoleV2"); _mA.Invoke(_a,null); _mB.Invoke(_b,null); } public void TryCastA() { try { Assembly _assembly =
    Assembly.LoadFrom(@"E:\Blog\Assemblies\v2\AssemblyX.dll"); Type Av2 = _assembly.GetType("AssemblyX.A"); object _a = Activator.CreateInstance(Av2); Console.WriteLine(typeof(AssemblyX.A).AssemblyQualifiedName); Console.WriteLine(Av2.AssemblyQualifiedName); (_a as AssemblyX.A).WriteToConsole(); } catch(Exception ex) { Console.WriteLine(ex.Message); } } }

    When you run the console application, you get the following output. Notice the object reference exception you would get, because of the invalid cast between the the two classes.

     

    You would get the same results if you used strongly named assemblies.

    Posted Apr 13 2005, 12:04 AM by rsakalley with 8 comment(s)
    Filed under:
  • Using AppDomain.Unload II

      There were a few mistakes in the last post on the AppDomain.Unload solution (thanks Manoj for pointing out) (John Papa wanted to know why I did not use LoadFile, thanks John, now I know should have written that MarshalByRef, just forgot it completely.) And sorry for this delayed update, damn weekend.

    First of all,I missed to mention the MarshalByRef derivation for the AssemblyLoader. This is essential because the Dispatch should be made to the secondary AppDomain, and if the AssemblyLoader is not a MarshalByRef object, the dynamic assembly (Tested there) will be loaded in the primary AppDomain, and therefore, the latest version will not run.So if you have just copied and pasted the code somewhere, it might not work. Just inherit MarshalByRef for the AssemblyLoader and it should work. The update is in red.

     

     [Serializable]
    public class AssemblyLoader : MarshalByRef
    {
    public void LoadAndRun()
    {

    Assembly _assembly = Assembly.Load(<< assembly file path>>);
    Type _type =_assembly.GetType(“Tested”);
    MethodInfo _method =_type.GetMethod("Test");
    _method.Invoke(Activator.CreateInstance(_type),null);

    }

    }

     

     

    Second thing, there is a workaround, if you do not want the calls to be dispatched to the secondary AppDomain. You can use the following -

    [Serializable]
    public class AssemblyLoader
    {
    public void Load()
    {
    FileStream _fileStream = File.OpenRead("Tested.dll");
    byte[] _assemblyAsByteArray = new byte[_fileStream.Length];
    _fileStream.Read(_assemblyAsByteArray,0,(int)_fileStream.Length);
    _fileStream.Close();
    Assembly _assembly = Assembly.Load(_assemblyAsByteArray);
    Type _type =_assembly.GetTypes()[0];
    MethodInfo _method =_type.GetMethod("Test");
    _method.Invoke(Activator.CreateInstance(_type),null);

    }

    }
     
    That is, do not inherit the AssemblyLoader from MarshalByRef, and Load the assembly as a byte array. This loads the latest version. 
    The good part here is that there are no calls dispatched on the secondary appdomain, so it should be faster. The bad break is,
    there is an upfront overload of File IO. And yes, I do not know if this is supported or not.
    Posted Apr 11 2005, 01:35 AM by rsakalley with 11 comment(s)
    Filed under:
More Posts Next page »