Testing Blog

Writing Testable Code

streda, augusta 06, 2008
Share on Twitter Share on Facebook
Google
Menovky: Misko Hevery

32 komentárov :

  1. Jonathan Pryor6. augusta 2008 o 10:16:00 GMT-7

    I don't know how to unit-test the main method!

    Obviously you have no imagination. You test the same method the same way you test static methods: provide known input, and test that the output is what you expect given the input.

    Which is exactly the same way you'd test Math.abs() and numerous other static methods. (Which is exactly the way I test C# extension methods, e.g. http://anonsvn.mono-project.com/source/branches/rocks-playground/Tests/Mono.Rocks.Tests/IEnumerableTest.cs)

    To make this "easy", you should attempt to mandate that static methods operate on no mutable state -- following the idioms of functional programming -- or provide some mechanism to reset the global state that the method operates on to a known value.

    Remember: global state is also an input to the static method if the method uses the global state.

    You can, of course, take this to a "higher level": console input and output is also global state, so if your main method reads from or writes to the terminal, you can have a shell-based unit test which invokes your program (with some set of arguments) and compares the programs output to what was actually generated.

    This isn't difficult. Tedious, sure, but not difficult, and extremely useful to do when first starting to write unit tests for a pre-existing project (which may not have used any OO design methodology to begin with).

    Just remember the first rule of testing any unit of code (method, library, program, operating system...): check the code's output against known input and compare against known-good output. The rest are details.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  2. Unknown7. augusta 2008 o 3:05:00 GMT-7

    "[If your] class has static methods that only operate on parameters [then] you have a class which mixes concerns"

    I have a class named Importer which has a static method:
    Customer ReadCustomer(IDataRecord record)

    This method only operates on its parameter. It creates a new Customer object from the IDataRecord.

    Could you please describe how this class 'mixes concerns'? I'm not entirely sure how it is doing so.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  3. John Webber7. augusta 2008 o 5:17:00 GMT-7

    Miško, in the paragraph about static methods you refer to "seems" - do you mean "seams?" Otherwise I'm not sure what you mean...

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  4. Michael Roger7. augusta 2008 o 8:23:00 GMT-7

    Sponge, I believe the point is that any pure method (that relies only on its parameters) can be separated into a pure utility class, leaving less code that depends on the class members.

    "Separation of concerns" didn't put a fine point on it, but the goal is to eliminate uneccessary dependencies, much like the Fuel/FuelTank example earlier.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  5. Unknown7. augusta 2008 o 8:32:00 GMT-7

    If you get past a number of typos and the non-working links, it looks like a hastily written, non-proofed copy.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  6. Gary Brunton7. augusta 2008 o 8:43:00 GMT-7

    Excellent article! I love seeing these types of topics from this blog.

    Keep them coming.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  7. Max Cantor7. augusta 2008 o 12:14:00 GMT-7

    You wrote:

    If you see a switch statement you should think polymorphisms. If you see the same if condition repeated in many places in your class you should again think polymorphism.

    Could you perhaps give a little code snippet that exemplifies this? That is, what would a switch statement "look like" when turned into a polymorphic solution instead?

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  8. Unknown7. augusta 2008 o 13:07:00 GMT-7

    Max "Could you perhaps give a little code snippet that exemplifies this?"

    Assume you have a class named "Message" with a method named "sendMessage()" that contains this fragment :

    if (this.messageType = messageTypes.Fax) {
    ...
    }

    then you should probably have a FaxMessage class that inherits from Message and overrides sendMessage().

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  9. Imran Fanaswala7. augusta 2008 o 13:38:00 GMT-7

    @Max,

    Let's say you are developing a chat service that combines various chat protocols, and you want to implement logout() functionality.

    Switch version:
    http://pastebin.com/f23bf0c6e

    Polymorphic version:
    http://pastebin.com/fae7a445

    Admittedly, the above example is not the most apt but it is based of a real world refactoring I did a while ago. If you want a more typical example, try http://hanuska.blogspot.com/2006/08/swich-statement-code-smell-and.html

    Regards,
    Imran Fanaswala

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  10. Groby7. augusta 2008 o 13:45:00 GMT-7

    Hm. You have me stumped with the "ask, don't look for" advice.

    Who exactly would I be asking for the objects I need if I *don't* pass in a ServiceLocator? A global service locator instead?

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  11. helios7. augusta 2008 o 13:50:00 GMT-7

    More about polymorphism:

    maybe examples on how to use polymorphism can be found in the strategy pattern (Gamma 1994). It happens a lot of time (the most when your building some kind of tool/framework) you need to do a generic work (loading database field values into an object, by example), but this generic thing has it's specialties (converting types, converting special values, getting the value, etc). That's when you delegate that special thing (converter.getValueFromBD(...)) and use polymorphism to implement it in various ways (IntegerConverter, ClobToStringConverter, StringConverter, etc, etc, etc).

    By the way: strategy is a pattern like template-method except that it preffers composition [using a strategy] than inheritance [overriding the template method]. It illustrate the point about composition vs. inheritance.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  12. helios7. augusta 2008 o 14:01:00 GMT-7

    groby:

    asking:

    There are two ways. None of them use a ServiceLocator.

    1) receiving what you need directly in the constructor/setter. I mean: if you need something let your client code give it to you.

    new Car(FuelTank)

    2) receiving a Provider (NOT A SERVICELOCATOR).
    It's a subttle diferrence:

    A ServiceLocator is bad because it's a general/global entry-point. It's application-aware, not component-aware. So your code becomes less independent.

    A Provider (as I propose it) is an interface defined by the very class you are writing and who implements it ONLY does that.

    example:

    new Engine(FuelProvider)

    as I cannot give fuel to the engine directly on the constructor (it's going to ask for it when it runs) I have to give it when the class wants. So that class (Engine) defines the interface FuelProvider:

    examples.car.engine.Engine
    examples.car.engine.FuelProvider

    and somebody implement it how he/she wants:

    examples.car.NormalFuelProvider implements
    examples.car.engine.FuelProvider
    {
    // uses FuelTank
    }

    NormalFuelProvider is more application-dependant that FuelProvider interface. It's fine because it's created for wiring things in an application (assume car is the application). At least, in the example is something that's made for creating a car with an Eingne and a FuelTank.

    Getting back to the ServiceLocator what I mean is you can implement a Provider that's aware of the ServiceLocator but your class Engine not.

    If you want to test it you can give an AllTheFuelYouWantProvider that do mock-like stuff so you can concentrate on the Engine. You don't have to worry about any ServiceLocator (or FuelTank), don't have to worry about application-like code, and your tests are happier.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  13. ihath7. augusta 2008 o 16:27:00 GMT-7

    interesting article

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  14. Max Cantor8. augusta 2008 o 12:11:00 GMT-7

    @Imran and @Michel:

    Thanks! This seems like something I've done for a while without knowing what it was called. I appreciate the explanation!

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  15. Dave Kirby8. augusta 2008 o 12:23:00 GMT-7

    This is an interesting article, but the list is rather confusing. Some of the titles are things that you SHOULD do, and some are things that you should NOT do. It is only when you read the body of the list that it becomes clear (and sometimes even then it is not always obvious). I suggest prepending each list item with DO or DONT to make it clear, or rewriting them to make them consistent.

    To be specific, all of the points are things you should NOT do, except for 2, 7 and 8, which you SHOULD do.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  16. Unknown26. augusta 2008 o 16:38:00 GMT-7

    If you have a spring project and you want to test a dao - how do you do that *easily*.

    Everyone just says, "use dbunit".

    But I don't see how that makes it easy.

    OdpovedaťOdstrániť
    Odpovede
    1. Anonymný14. septembra 2012 o 0:04:00 GMT-7

      Build yourself a test fixture using an in-mem database, and add database initialization code to the test fixture class. Sure, it's some overhead, but if you do it right, you only do it once for all DAO tests you write in an application - and IME there are many of them.

      Odstrániť
      Odpovede
        Odpovedať
    2. Anonymný14. septembra 2012 o 0:27:00 GMT-7

      Organizing your code into value objects and services is highly non-OO, and was named by (IIRC) Fowler the anemic domain model. I have used it successfully in several LOB apps, but it is specifically damaging when the interactions between your domain-specific objects are rich and complex (like for example in a physical simulation of a system if interacting particles). In such cases, organizing your code into value objects and services rightout harms testability. Therefore I wouldn't include this advice in the list.

      Odstrániť
      Odpovede
        Odpovedať
    3. Misraji28. decembra 2012 o 20:00:00 GMT-8

      @Florin:
      I do follow your argument about not organizing code into value object and service objects for simulation software.

      But my theoretical understand of OO is that an object is Procedural abstraction of Data. That is data being represented purely by its behavior.
      Service Objects perfectly fit the definition. What is being hidden, is their own state, which should be nobody's concern.

      OTH, not all data can be represented by behavior only. In such cases, having a value object makes sense.

      Thus IMHO, the advice about dividing the code into Value Objects and Service Objects still seems reasonable.

      Is my reasoning incorrect?

      Odstrániť
      Odpovede
        Odpovedať
    4. Odpovedať
  17. Ran Tavory28. júna 2009 o 6:23:00 GMT-7

    About Singletons, I completely agree. I posted this article on my blog: http://prettyprint.me/2009/06/24/beware-of-the-singleton/

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  18. Edward Huynh2. septembra 2009 o 23:38:00 GMT-7

    Excellent topic and content. Keep them coming

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  19. Geshan Manandhar22. marca 2010 o 7:34:00 GMT-7

    If I could wrap my head around it, I"ll try :).

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  20. jennifer14. mája 2010 o 5:03:00 GMT-7

    it's good to see this information in your post, i was looking the same but there was not any proper resource, thanx now i have the link which i was looking for my research.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  21. Kalle Karlberg21. mája 2011 o 3:05:00 GMT-7

    Great article. I tried for one hour+ to make this point to a colleage y-day. I'll just send her this article.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  22. Mike2. decembra 2011 o 16:03:00 GMT-8

    Good article, most points I agree with. However, there is a strong Java/C# bias in your explanations (or pure OOP bias), and it might be good to stress that fact as some points don't apply as strongly to other languages. Also, this statement made be jump out of my chair:

    "Polymorphism: at compile-time the method you are calling can not be determined"

    You need to review your basic software engineering knowledge. The definition you give pertains to "dynamic binding", not polymorphism. Polymorphism is essentially the concept of substitutability of types. In other words, being able to substitute one object-type for another and be able to reuse the same method that uses either types is the key aspect of polymorphism (i.e. the object types are polymorphic types and the functions using them are polymorphic functions). This does NOT require dynamic binding, it is only if you need to make this substitution at run-time that dynamic binding is required. Haven't you heard of something called "static polymorphism" (i.e. polymorphism that is realized at compile-time). This also exemplifies my point about the strong OOP bias in your article. I write an enormous amount of procedural code (in C++), heavily relying on static polymorphism, and thus, has a lot of "seams" making the construction of unit-tests very easy (and generally sticking to state-less functional programming is also a huge benefit in that regard). Certainly, in OOP, good use of dynamic polymorphism will make unit-testing a lot easier, but this does not mean that procedural programming (that doesn't use dynamic polymorphism) is hard to unit-test, it's just hard to do so if you suck at writing procedural code.

    So overall, I would say that point 6 should be taken out (or left with a strong caveat that this applies only to highly restrictive programming languages that don't allow you to achieve static polymorphism). Then, points 4 and 5 are the same (do you really think anyone who knows what a Singleton is doesn't know that it's forms a global state). Point 3 only applies to languages with reference-semantics with non-deterministic construction models (Java/C# and the like), in a language like C++, this point is mute (unless you are emulating Java/C# style OOP in C++, which is just a very bad style of C++). The remaining points are good IMO.

    Just my grain of salt.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  23. Unknown20. júla 2012 o 5:25:00 GMT-7

    Do you test the code that creates the object graph? If so, how?

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  24. Misraji29. decembra 2012 o 13:42:00 GMT-8

    How does one deal with dynamically created objects (say) like objects representing email?

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  25. Unknown21. augusta 2013 o 7:57:00 GMT-7

    I guess "branches" would be the correct term as opposed to "seams".

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  26. Robert Peszek8. októbra 2014 o 18:20:00 GMT-7

    Continuing on the OOP bias point (Mike December 2, 2011).
    FP is becoming more and more popular and OO languages allow for more and more of a FP/OOP mix.

    If you think about this list in therms of FP, all points are N/A!

    In this context, I would like to suggest a shorter list to produce a much more testable code:
    1) limit side-effects
    2) isolate side-effects

    Also, in the context of FP, I very much disagree with point 6. The term 'method' is somewhat redeeming but...
    A true FP language like Haskell will have a very 'static' feel to it. In OOP/FP hybrid if you want to code with functions instead of methods these functions will need to have static presence too. For example: if 'reduce' is a function that accept an accumulator and a list (instead of being a method owned by the list), it has to exist outside of the list object. I took the approach of using lots of static definitions when designing fpiglet (FP library for Groovy) and I believe it to be some of the most testable code I ever done within the boundaries of an OO language.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  27. Unknown22. októbra 2016 o 12:31:00 GMT-7

    RDM vs. ADM
    ----------------------------------------------------------------

    If you separate logic from data in an Object Oriented language, you actually fall back to procedural programming. (A.K.A, by Fowler, "ADM")

    Many companies do that for the sake of testing.

    However, if you still want to write real Object Oriented and benefit a rich domain model:

    1. Separate your project to modules.
    2. Each module will have a thin service layer made of stateless logic.
    3. Use "new" to instantiate business objects.
    4. Use service locator or IoC container to resolve services provided by other modules.

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  28. MPursley9. októbra 2018 o 17:19:00 GMT-7

    Thanks for the article. Awesome tips!

    While reading through it, I found some things that sound like typos or minor grammatical errors? I'll post them here, in case you have time/interest to fix them. :) I'll post them into the copy on your blog too.


    Thanks!
    Matt

    ___
    - "OK, you got rid of your new operators in you application code." ->
    "OK, you got rid of your new operators in your application code."

    - "Global state is bad from theoretical, maintainability, and understandability point of view," ->
    "Global state is bad from theoretical, maintainability, and understandability points of view,"

    - "The core of the issue is that the global instance variables have transitive property!" ->
    "The core of the issue is that the global instance variables have a transitive property!"

    - "Seams are needed so that you can isolate the unit of test." ->
    "Seams are needed so that you can isolate the unit test."

    - "If you build an application with nothing but static methods you have procedural application." ->
    "If you build an application with nothing but static methods you have a procedural application."

    - "I don't know how to test application without seams." ->
    "I don't know how to test an application without seams."

    - "How much a static method will hurt from a testing point of view depends on where it is in you application call graph." ->
    "How much a static method will hurt from a testing point of view depends on where it is in your application call graph."

    - "At run-time you can not chose a different inheritance, but you can chose a different composition, this is important for tests as we want to test thing in isolation." ->
    "At run-time you can not choose a different inheritance, but you can choose a different composition, this is important for tests as we want to test a thing in isolation."

    - "This will clutter the focus of test" ->
    "This will clutter the focus of the test"

    - "This helps testing since simpler/smaller class is easier to test." ->
    "This helps testing since a simpler/smaller class is easier to test."

    - "If summing up what the class does includes the word "and", or class would be challenging for new team members to read and quickly "get it", or class has fields that are only used in some methods, or class has static methods that only operate on parameters than you have a class which mixes concerns." ->
    "If summing up what the class does includes the word "and", or the class would be challenging for new team members to read and quickly "get it", or the class has fields that are only used in some methods, or class has static methods that only operate on parameters than you have a class which mixes concerns."

    - "These classes are hard to tests since there are multiple objects hiding inside of them and as a resulting you are testing all of the objects at once." ->
    "These classes are hard to tests since there are multiple objects hiding inside of them and as a result, you are testing all of the objects at once."
    ___

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
  29. Google Testing Bloggers31. októbra 2018 o 7:17:00 GMT-7

    Fixed! Thanks!

    OdpovedaťOdstrániť
    Odpovede
      Odpovedať
Pridať komentár
Načítať viac...

The comments you read and contribute here belong only to the person who posted them. We reserve the right to remove off-topic comments.

  

Labels


  • TotT 104
  • GTAC 61
  • James Whittaker 42
  • Misko Hevery 32
  • Code Health 31
  • Anthony Vallone 27
  • Patrick Copeland 23
  • Jobs 18
  • Andrew Trenk 13
  • C++ 11
  • Patrik Höglund 8
  • JavaScript 7
  • Allen Hutchison 6
  • George Pirocanac 6
  • Zhanyong Wan 6
  • Harry Robinson 5
  • Java 5
  • Julian Harty 5
  • Adam Bender 4
  • Alberto Savoia 4
  • Ben Yu 4
  • Erik Kuefler 4
  • Philip Zembrod 4
  • Shyam Seshadri 4
  • Chrome 3
  • Dillon Bly 3
  • John Thomas 3
  • Lesley Katzen 3
  • Marc Kaplan 3
  • Markus Clermont 3
  • Max Kanat-Alexander 3
  • Sonal Shah 3
  • APIs 2
  • Abhishek Arya 2
  • Alan Myrvold 2
  • Alek Icev 2
  • Android 2
  • April Fools 2
  • Chaitali Narla 2
  • Chris Lewis 2
  • Chrome OS 2
  • Diego Salas 2
  • Dori Reuveni 2
  • Jason Arbon 2
  • Jochen Wuttke 2
  • Kostya Serebryany 2
  • Marc Eaddy 2
  • Marko Ivanković 2
  • Mobile 2
  • Oliver Chang 2
  • Simon Stewart 2
  • Stefan Kennedy 2
  • Test Flakiness 2
  • Titus Winters 2
  • Tony Voellm 2
  • WebRTC 2
  • Yiming Sun 2
  • Yvette Nameth 2
  • Zuri Kemp 2
  • Aaron Jacobs 1
  • Adam Porter 1
  • Adam Raider 1
  • Adel Saoud 1
  • Alan Faulkner 1
  • Alex Eagle 1
  • Amy Fu 1
  • Anantha Keesara 1
  • Antoine Picard 1
  • App Engine 1
  • Ari Shamash 1
  • Arif Sukoco 1
  • Benjamin Pick 1
  • Bob Nystrom 1
  • Bruce Leban 1
  • Carlos Arguelles 1
  • Carlos Israel Ortiz García 1
  • Cathal Weakliam 1
  • Christopher Semturs 1
  • Clay Murphy 1
  • Dagang Wei 1
  • Dan Maksimovich 1
  • Dan Shi 1
  • Dan Willemsen 1
  • Dave Chen 1
  • Dave Gladfelter 1
  • David Bendory 1
  • David Mandelberg 1
  • Derek Snyder 1
  • Diego Cavalcanti 1
  • Dmitry Vyukov 1
  • Eduardo Bravo Ortiz 1
  • Ekaterina Kamenskaya 1
  • Elliott Karpilovsky 1
  • Elliotte Rusty Harold 1
  • Espresso 1
  • Felipe Sodré 1
  • Francois Aube 1
  • Gene Volovich 1
  • Google+ 1
  • Goran Petrovic 1
  • Goranka Bjedov 1
  • Hank Duan 1
  • Havard Rast Blok 1
  • Hongfei Ding 1
  • Jason Elbaum 1
  • Jason Huggins 1
  • Jay Han 1
  • Jeff Hoy 1
  • Jeff Listfield 1
  • Jessica Tomechak 1
  • Jim Reardon 1
  • Joe Allan Muharsky 1
  • Joel Hynoski 1
  • John Micco 1
  • John Penix 1
  • Jonathan Rockway 1
  • Jonathan Velasquez 1
  • Josh Armour 1
  • Julie Ralph 1
  • Kai Kent 1
  • Kanu Tewary 1
  • Karin Lundberg 1
  • Kaue Silveira 1
  • Kevin Bourrillion 1
  • Kevin Graney 1
  • Kirkland 1
  • Kurt Alfred Kluever 1
  • Manjusha Parvathaneni 1
  • Marek Kiszkis 1
  • Marius Latinis 1
  • Mark Ivey 1
  • Mark Manley 1
  • Mark Striebeck 1
  • Matt Lowrie 1
  • Meredith Whittaker 1
  • Michael Bachman 1
  • Michael Klepikov 1
  • Mike Aizatsky 1
  • Mike Wacker 1
  • Mona El Mahdy 1
  • Noel Yap 1
  • Palak Bansal 1
  • Patricia Legaspi 1
  • Per Jacobsson 1
  • Peter Arrenbrecht 1
  • Peter Spragins 1
  • Phil Norman 1
  • Phil Rollet 1
  • Pooja Gupta 1
  • Project Showcase 1
  • Radoslav Vasilev 1
  • Rajat Dewan 1
  • Rajat Jain 1
  • Rich Martin 1
  • Richard Bustamante 1
  • Roshan Sembacuttiaratchy 1
  • Ruslan Khamitov 1
  • Sam Lee 1
  • Sean Jordan 1
  • Sebastian Dörner 1
  • Sharon Zhou 1
  • Shiva Garg 1
  • Siddartha Janga 1
  • Simran Basi 1
  • Stan Chan 1
  • Stephen Ng 1
  • Tejas Shah 1
  • Test Analytics 1
  • Test Engineer 1
  • Tim Lyakhovetskiy 1
  • Tom O'Neill 1
  • Vojta Jína 1
  • automation 1
  • dead code 1
  • iOS 1
  • mutation testing 1


Archive


  • ►  2025 (1)
    • ►  jan (1)
  • ►  2024 (13)
    • ►  dec (1)
    • ►  okt (1)
    • ►  sep (1)
    • ►  aug (1)
    • ►  júl (1)
    • ►  máj (3)
    • ►  apr (3)
    • ►  mar (1)
    • ►  feb (1)
  • ►  2023 (14)
    • ►  dec (2)
    • ►  nov (2)
    • ►  okt (5)
    • ►  sep (3)
    • ►  aug (1)
    • ►  apr (1)
  • ►  2022 (2)
    • ►  feb (2)
  • ►  2021 (3)
    • ►  jún (1)
    • ►  apr (1)
    • ►  mar (1)
  • ►  2020 (8)
    • ►  dec (2)
    • ►  nov (1)
    • ►  okt (1)
    • ►  aug (2)
    • ►  júl (1)
    • ►  máj (1)
  • ►  2019 (4)
    • ►  dec (1)
    • ►  nov (1)
    • ►  júl (1)
    • ►  jan (1)
  • ►  2018 (7)
    • ►  nov (1)
    • ►  sep (1)
    • ►  júl (1)
    • ►  jún (2)
    • ►  máj (1)
    • ►  feb (1)
  • ►  2017 (17)
    • ►  dec (1)
    • ►  nov (1)
    • ►  okt (1)
    • ►  sep (1)
    • ►  aug (1)
    • ►  júl (2)
    • ►  jún (2)
    • ►  máj (3)
    • ►  apr (2)
    • ►  feb (1)
    • ►  jan (2)
  • ►  2016 (15)
    • ►  dec (1)
    • ►  nov (2)
    • ►  okt (1)
    • ►  sep (2)
    • ►  aug (1)
    • ►  jún (2)
    • ►  máj (3)
    • ►  apr (1)
    • ►  mar (1)
    • ►  feb (1)
  • ►  2015 (14)
    • ►  dec (1)
    • ►  nov (1)
    • ►  okt (2)
    • ►  aug (1)
    • ►  jún (1)
    • ►  máj (2)
    • ►  apr (2)
    • ►  mar (1)
    • ►  feb (1)
    • ►  jan (2)
  • ►  2014 (24)
    • ►  dec (2)
    • ►  nov (1)
    • ►  okt (2)
    • ►  sep (2)
    • ►  aug (2)
    • ►  júl (3)
    • ►  jún (3)
    • ►  máj (2)
    • ►  apr (2)
    • ►  mar (2)
    • ►  feb (1)
    • ►  jan (2)
  • ►  2013 (16)
    • ►  dec (1)
    • ►  nov (1)
    • ►  okt (1)
    • ►  aug (2)
    • ►  júl (1)
    • ►  jún (2)
    • ►  máj (2)
    • ►  apr (2)
    • ►  mar (2)
    • ►  jan (2)
  • ►  2012 (11)
    • ►  dec (1)
    • ►  nov (2)
    • ►  okt (3)
    • ►  sep (1)
    • ►  aug (4)
  • ►  2011 (39)
    • ►  nov (2)
    • ►  okt (5)
    • ►  sep (2)
    • ►  aug (4)
    • ►  júl (2)
    • ►  jún (5)
    • ►  máj (4)
    • ►  apr (3)
    • ►  mar (4)
    • ►  feb (5)
    • ►  jan (3)
  • ►  2010 (37)
    • ►  dec (3)
    • ►  nov (3)
    • ►  okt (4)
    • ►  sep (8)
    • ►  aug (3)
    • ►  júl (3)
    • ►  jún (2)
    • ►  máj (2)
    • ►  apr (3)
    • ►  mar (3)
    • ►  feb (2)
    • ►  jan (1)
  • ►  2009 (54)
    • ►  dec (3)
    • ►  nov (2)
    • ►  okt (3)
    • ►  sep (5)
    • ►  aug (4)
    • ►  júl (15)
    • ►  jún (8)
    • ►  máj (3)
    • ►  apr (2)
    • ►  feb (5)
    • ►  jan (4)
  • ▼  2008 (75)
    • ►  dec (6)
    • ►  nov (8)
    • ►  okt (9)
    • ►  sep (8)
    • ▼  aug (9)
      • Taming the Beast (a.k.a. how to test AJAX applicat...
      • Root Cause of Singletons
      • TotT: Sleeping != Synchronization
      • Where Have All the Singletons Gone?
      • Singletons are Pathological Liars
      • TotT: 100 and counting
      • TotT: A Matter of Black and White
      • Writing Testable Code
      • GTAC Attendance Application deadline Aug15
    • ►  júl (9)
    • ►  jún (6)
    • ►  máj (6)
    • ►  apr (4)
    • ►  mar (4)
    • ►  feb (4)
    • ►  jan (2)
  • ►  2007 (41)
    • ►  okt (6)
    • ►  sep (5)
    • ►  aug (3)
    • ►  júl (2)
    • ►  jún (2)
    • ►  máj (2)
    • ►  apr (7)
    • ►  mar (5)
    • ►  feb (5)
    • ►  jan (4)

Feed

  • Google
  • Privacy
  • Terms