The Holy Java

Building the right thing, building it right, fast

Archive for the ‘Testing’ Category

Hack: Quickly Verify That All Your Mocha/Chai Tests Have Valid Assertions

Posted by Jakub Holý on May 6, 2015

Chai is a popular Node/browser assertion library. However – as everything – it has its flaws. An important flaw is that it performs checks on property access – and if you e.g. misspell the name of an assertion, it will be just ignored (for there is no way for Chai to know that you tried to access a non-existent property). This may be fixed in the future with ES6 proxies but so far you risk having tests that actually do not test anything. Though you should of course always develop your tests so that they initially fail and thus you know they actually assert something :-).

Anyway, there is a neat quick way to verify that all your tests have at least one valid assertion – simply replace expect with expect.not.
Read the rest of this entry »

Posted in Testing | Tagged: | Comments Off on Hack: Quickly Verify That All Your Mocha/Chai Tests Have Valid Assertions

Git pre-commit hook that fails if “it.only” used (Jest/Jasmine)

Posted by Jakub Holý on March 27, 2015

One of the annoying things with Jest is that while it enables you to run only a single test by using it.only, it does not report this in any noticeable way. Thus you can end up in the same situation as we did, not running many tests without knowing it. (Oh yeah, if we only did review the code properly …).

This git pre-commit hook will fail when you introduce it.only into the code:

Posted in Testing | Tagged: , | 4 Comments »

Challenging Myself With Coplien’s Why Most Unit Testing is Waste

Posted by Jakub Holý on January 26, 2015

James O. Coplien has written in 2014 the thought-provoking essay Why Most Unit Testing is Waste and further elaborates the topic in his Segue. I love testing but I also value challenging my views to expand my understanding so it was a valuable read. When encountering something so controversial, it’s crucial to set aside one’s emotions and opinions and ask: “Provided that it is true, what in my world view might need questioning and updating?” Judge for yourself how well have I have managed it. (Note: This post is not intended as a full and impartial summary of his writing but rather a overveiw of what I may learn from it.)

Perhaps the most important lesson is this: Don’t blindly accept fads, myths, authorities and “established truths.” Question everything, collect experience, judge for yourself. As J. Coplien himself writes:

Be skeptical of yourself: measure, prove, retry. Be skeptical of me for heaven’s sake.

I am currently fond of unit testing so my mission is now to critically confront Coplien’s ideas and my own preconceptions with practical experience on my next projects.

I would suggest that the main thing you take away isn’t “minimize unit testing” but rather “value thinking, focus on system testing, employ code reviews and other QA measures.”

I’ll list my main take-aways first and go into detail later on:
Read the rest of this entry »

Posted in Testing | Tagged: | 1 Comment »

Running JavaScript Tests On a CI Server With Karma, Chrome And Fake X

Posted by Jakub Holý on January 13, 2015

So I want to run my JavaScript tests in a browser on our CI server. But the server has no graphical environment and the tests do not run under PhantomJS 1.x because it uses too old WebKit without ES5. The solution? Use a real browser and fake X via Xvfb. The browser I use is Chrome though Firefox would like work as well.

In code:
Read the rest of this entry »

Posted in Languages, Testing | Tagged: | Comments Off on Running JavaScript Tests On a CI Server With Karma, Chrome And Fake X

Continuous Delivery Digest: Ch.9 Testing Non-Functional Requirements

Posted by Jakub Holý on January 8, 2015

(Cross-posted from blog.iterate.no)

Digest of chapter 9 of the Continuous Delivery bible by Humble and Farley. See also the digest of ch 8: Automated Acceptance Testing.

(“cross-functional” might be better as they too are crucial for functionality)

  • f.ex. security, usability, maintainability, auditability, configurability but especially capacity, throughput, performance
  • performance = time to process 1 transaction (tx); throughput = #tx/a period; capacity = max throughput we can handle under a given load while maintaining acceptable response times.
  • NFRs determine the architecture so we must define them early; all (ops, devs, testers, customer) should meet to estimate their impact (it costs to increase any of them and often they go contrary to each other, e.g. security and performance)
  • das appropriate, you can either create specific stories for NFRs (e.g. capacity; => easier to prioritize explicitely) or/and add them as requirements to feature stories
  • if poorly analyzed then they constrain thinking, lead to overdesign and inappropriate optimization
  • only ever optimize based on facts, i.e. realistic measurements (if you don’t know it: developers are really terrible at guessing the source of performance problems)

A strategy to address capacity problems:

Read the rest of this entry »

Posted in Testing | Tagged: , | Comments Off on Continuous Delivery Digest: Ch.9 Testing Non-Functional Requirements

Notes On Automated Acceptance Testing (from the Continuous Delivery book)

Posted by Jakub Holý on January 8, 2015

(Cross-posted from blog.iterate.no)

These are my rather extensive notes from reading the chapter 8 on Automated Acceptance Testing in the Continuous Delivery bible by Humble and Farley. There is plenty of very good advice that I just had to take record of. Acceptance testing is an exciting and important subject. Why should you care about it? Because:

We know from experience that without excellent automated acceptance test coverage, one of three things happens: Either a lot of time is spent trying to find and fix bugs at the end of the process when you thought you were done, or you spend a great deal of time and money on manual acceptance and regression testing, or you end up releasing poor-quality software.

Read the rest of this entry »

Posted in SW development, Testing | Tagged: , | Comments Off on Notes On Automated Acceptance Testing (from the Continuous Delivery book)

Notes From CodeMesh 2014

Posted by Jakub Holý on November 3, 2014

My consise highlights from CodeMesh 2014.

Philip Potter has very good CodeMesh notes as well, as usually.

TODO: Check out the papers mentioned in the  NoSQL is Dead talk. (<- slides)

Tutorial: QuickCheck (John Hughes)

General
  • QC => Less code, more bugs found
  • QC tests are based on models of the system under test – with some kind of a simple/simplified state, legal commands, their preconditions, postconditions, and how they impact the state. The model is typically much smaller and simpler than the imple code.
  • QuickCheck CI (quickcheck-ci.com) – free on-line service for running CI tests for a GitHub project. Pros: You don’t need QC/Erlang locally to play with it, it provides history of tests (so you never loose a failed test case), it shows test coverage also for failed tests so you see which code you can ignore when looking for the cause.
  • See John’s GitHub repo with examples – https://github.com/rjmh/
Shrinking (a.k.a. simplification)
  • Doesn’t just make the example shorter by leaving things out by tries a number of strategies to simplify the exmple, typically defined by the corresponding generators – f.ex. numbers are simplified to 0, lists to earlier elements (as in “(elements [3, 4, 5])”) etc.
  • You may implement your own shrinking strategies. Ex.: Replace a command with “sleep(some delay)” – so that we trigger errors due to timeouts. (A noop that just waits for a while is simpler than any op).
Bug discovery
  1. Run QC; assuming a test failed:
  2. Instead of diving into the implementation, use first QC to check your hypothesis of what constitutes “bad input” by excluding the presumed bad cases – f.ex. “it fails when input has 8 characters” => exclude tests with 8 and rerun, if you find new failures you know the hypothesis doesn’t cover all problems – and you will perhaps refine it to  “fails when it has a multiple of 8 chars etc. We thus learn more about the wrong behavior and its bounds. Assumption we want to verify: No (other) tests will fail.
  3. Do the opposite – focus on the problem, i.e. modify the test case to produce only “bad cases”. Assumption we want to verify: all tests will fail.
QC vs. example-based testing

QC code tends to be 3-6* smaller than implementation (partly thanks to the consiseness of Erlang) and fairly simple.

The case of Vovlo: 3k pages of specs, 20 kLOC QC, 1M LOC C implementations, found 200 bugs and 100 problems (contradictions, unclarities) in the specs. It took 2-3 years of working on it on and off.

Erlang dets storage race conditions: 100 LOC QC, 6 kLOC Erlang impl.

Testing stateful stuff

Invoke dfferent API calls (“commands”) until one of presumabely legal calls fails due to an accumulated corrupted state. This is an iterative process where we evolve our model of the system – commands, their preconditions (when they can be legally invoked), postconditions, and our repreentation of the state.

Ex.: Testing of a circular queue. Commads: push (legal on non-full queue), get (legal on non-empty), create new => generates sequences of new and pushs and gets.

Testing race conditions

Precondition: Run on a multicore PC or control the process scheduler.

  • There are many possible correct results (valid interleavings) of parallel actions => impractical to enumerate and thus to test with example-based tests
  • Correct result is such that we can order (interleave) the concurrently executed actions such that we get a sequential execution yielding the same result. F.ex. an incorrect implementation of a sequence number generator could return the same number to two concurrent calls – which is not possible if the calls were done sequentially.
Testing data structures

Map the DS to a simpler one and use that as the model – f.ex. a list for a tree (provided there is a to_list function for the tree).

Tutorial: Typed Clojure (Ambrose Bonnaire-Sergeant)

Note: The documentation (primarily introductory one) could be better

Resources
Defining types
  1. separately: (ann ..)
  2. around: wrap in (ann-form <defn> <type def.>)
  3. inside: use t/fn, t/defprotocol etc.
Gradual introduction of typed.clojure
  • wrap everything in (t/tc-ignore …)
  • for unchecked fns you depend on, add (ann ^:no-check somefn […])
  • If you stare at a type error, consider using contracts (prismatic/Schema or pre/post conds etc.)
Other

Keynote: Complexity (Jessica Kerr, Dan North)

  • Always have tasks of all three types: research (=> surface conplexity), kaizen (cont. improvement, improvement of the imprv. process), coding – these 3 interlave the whole time
  • A team needs skills in a number of areas, it isn’t just coding – evaluation of biz valuedelivered, monitoring, programming, testing, deployment, DB, FS, networks, … .

Keynote: Tiny (Chad Fowler)

Keep things tiny to be efficient (tiny changes, tiny teams, tiny projects, …).

  • Research by armies and in SW dev [TODO: find the two slides / qsm, Scrum] shows that teams of max 5-6 work best
    • Teams of 7+ take considerably more time and thus money (5* more wrt. one study) to complete the same thing
    • => small, autonomous teams with separate responsabilities (decomosition, SRP etc. FTW!)
  • Human capacity to deal with others is limited – one company creates a new department whenever size exceeds 100
  • Big projects fail; Standish CHAOS report – only cca 10% larger projects succeed compared to nearly 80% of small ones (summed together: 39% succeed)
  • Note: 1 month is not a short iteration

Distributed Programming (Reid Draper)

RPC is broken

– it tries to pretend a remote call is same as local but:

  • what if the call never returns?
  • the connection breaks? (has the code been executed or not yet?)
  • what about serialization of arguments (file handles, DB conn.,…)

It ignores the special character of a remote code and the 8 fallacies of distributed progr.

Message passing

is batter than RPC. There is also less coupling as the receiver itself decides what code to call for a specific message.

Bloom

The Bloom lang from the BOOM research project explores new, better ways of distributed programming. Currently implemented as a Ruby DSL.

From its page (highlight mine):

Traditional languages like Java and C are based on the von Neumann model, where a program counter steps through individual instructions in order. Distributed systems don’t work like that. Much of the pain in traditional distributed programming comes from this mismatch:  programmers are expected to bridge from an ordered programming model into a disordered reality that executes their code.  Bloom was designed to match–and exploit–the disorderly reality of distributed systems.  Bloom programmers write programs made up of unordered collections of statements, and are given constructs to impose order when needed.

Correctness testing of concurrent stuff
  • Unit testing unsuitable – there are just too many combinations of correct results and can only test the cases the dev can think of
  • => generate the tests – property-based testing / QuickCheck
  • PULSE – an addon to property-based testing that tries to trigger concurrency problems by using a scheduler that tries different interleavings of actions (randomly but repeatedly) [Erlang]
  • Simulation testnng – Simulant
Benchmarking

Beware the effects of GC, page cache, cronjob (e.g. concurrently running backup), SW updates => running a simple load test for few mins is not enough.

Cheats & Liars: The Martial Art of Protocol Design (Pieter Hintjens)

Pieter is the brain behind AMQP, ZeroMQ and EdgeNet (protocols for anonymous, secure, peer-to-peer internet). He has shared great insights into designing good protocols, the dirty business surrounding protocols and standardization, and troll-proof organization of communities (as a self-roganizing, distributed team).

More: See Ch.6 The ØMQ Community in the online The ZeroMQ Guide – for C Developers. (He has also other interesting online or paid books.)

  • Protocol is a contract for working together
  • IT should be minimalistic and specific, name the participants, …
  • Protocols and their strandardization are prey to “psychopatic” organizations that want to hijack them for their own profit (by pushing changes that benefit them, taking over the standardization process, …) (Pieter has experienced it e.g. with AMQP; these trolls always show up). It’s advantegous to take control of a successful protocol so that you can make money off it or build stuff on it and sell that. Examples:
    • Microsoft MS Doc XML  – this “open” spec f.ex. reportedly defines that one functions works “as Word 95”
    • A company pushing changes that nobody else really understands, thus undermining compatibility of implementations
    • Pushing such changes that an implementor can claim compliance to the standard yet implement it so that his products only work with his products
    • Crazy/proprieetary protocol extensions, patenting/trademarking/copyrighting the spec (e.g. TM on Bluetooth)
  • Hijacking-safe protocol creation process (beware “predatory maliciousness”):
    • The specs is GPL => nobody can capture it (e.g. ZeroMQ)
    • The community has clear rules and deals with trolls by kicking them out
    • There is a good process for evolving the spec
  • How to spec i protocol?
    • Start with a very, very small and simple contract – only add things that you desperately need – e.g. ZeroMQ v1 had no versioning, security, metadata (versioning added in v2, metadata in v3, ecurity later). You don’t know what you really need until you try it. F.ex. even the original AMQP has 60-75% waste in it!!!!
    • Do very slow and gradual evolution
    • Layering is crucial – keep your protocol on one layer, only specify relevant things, leave the other layers for other specs so they can evolve and age in different speed; the more in a spec the earlier will st. be outdated (Pizza contract says nothing about the kitchen, f.ex.)
  • Community and cooperation (See the Ch.6 The ØMQ Community mentioned above.)
    • community needs clear rules to keep trolls away (and they always pop up)
    • don’t just absorb the damage trolls do, ban them
    • self-org., decentralized team

PureScript (Bodil Stokke)

Working with larger JavaScript apps (> 100 LOC :-)) is painful, primarily due to the lack of type checking and thus requiring one to take lot of care when chaning code so that nothing breaks at runtime. TypeScript is a possible solution but it still feels limited.

PureScript is very Haskell-like language compiled to JS. It is a pure functional lang, effects are performed only via the Effect Monad (Eff). It is pragmatic w.r.t. interoperability – it is possible to embedd JS code and just add a signature to it, the compiler will trust it.

Moreover, you can use property-basd testing with QuickCheck and Functional Reactive Programming with Bodil’s Signal library. Isn’t that wonderful?!

See the PureScript Is Magic code at GitHub, primarily the 150 LOC Main.purs.

<3

Category theory notes:

  • Semigroup is a domain with a cumulative operation (e.g. ints with +)
  • Monoid (?) is a semigroup with a unit element, i.e. one where “element operation unit = element” as 0 for + or 1 for *.

Megacore, Megafast, Megacool (Kevin Hammond)

Interesting research project ParaPhrase for parallelization of code through automatic refactoring and application of any of supported topologies (Farm, Pipeline, Map, …) – ParaPhrase-ict.eu and www.project-advance.eu (in general the promises of automatizatio regarding fixing software development problems have have hugely underdelivered but still something might be possible). In some cases their solution managed to do in hours what a developer did in days.

Quote Bob Harper:

The only thing that works for parallelism is functional programming

PS: C++17 is going to have support for parallel and concurrent programming.

 Categories for the Working Programmer (Jeremy Gibbons)

An elementary intro into category theory in 10 points, yet I got immediately lost. It might be worth to study the slides and look for more resources at the author’s uni page and not-so-active blog Patterns in Functional Programming .

 NoSQL is Dead (Eric Redmond)

Main message: There is just too many differences between NoSQL DBs for this expression to be meaningful.

Lobby talks

Hacking people

I had an inpiring lunch chat with Chad and a Polish lady whose name I unfortunately don’t know. Their companies do fascinating stuff to leverage the potential of their humans – one has replaced top-down management wrt. projects with environment where there are clear objectives (increase monthly active users) and the freedom to come with ideas to contribute to them, recruit other people for the idea and, if successful, go implement it (while continually measuring against the objectives). Clearly enough it is not easy, some people have troubles trying to manage everything or doing what they believe in without checking the real implect on the objectives etc. but it already provides more value then before. This has been going on for just a few months so hopefully when it settles more we will hear about their experience.

The other company realized that people are different (wow! how could our industry ignore that?!) and started to go psychological profiling of employees to understand what type of team member they are – a driver, a worker, a critic who is always hunting for possible issues and problems etc. And they compose teams so that they have the right mix of different personalities to avoid both insurpasable conflicts and the risks of group-think.

I believe this is the future of our industry – really understand people and “hack” our organizations to leverage that for greater happiness and better results.

Non-talks

  • Jessica Kerr: Simulation of team work and the effect of (no) slack

    – what happens when you let your programmers crunch work without any slack time? And when you introduce slack? Jessica has made this Scala simulation to produce the results we would expect – much more even production in the slack case, lot of rework after deploying features in the non-slack version. Not at all scientific but very nice when you want to *show* your higher-ups what happens when you do the former or the latter. Some people hear much more to a visual stimuli (even though totally made to conform to the message you want to get across) than tons of theory.

  • Aphyr – [313] Strong consistency models – “strong consistency” is a much broader term than I expected and not all consistency models are so consistent :-) Check out especially this consistency family tree image.

Posted in Languages, Testing, Tools | Tagged: , , | Comments Off on Notes From CodeMesh 2014

Fixing clojurescript.test failing with “ReferenceError: Can’t find variable: cemerick”

Posted by Jakub Holý on May 21, 2014

ClojureScript.test (0.3.0; cemerick.cljs.test) may fail with this confusing exception:

ReferenceError: Can't find variable: cemerick

due to couple of reasons:

  1. Your test namespaces do not require cemerick.cljs.test (and thus it is missing from the compiled .js; requiring macros is not enough)
  2. cljsbuild has not included any of your test files (due to wrong setup etc.; this is essentially another form of #1)
  3. You are trying to test with the node runner but have built with :optimizations :none or :whitespace (for node you need to concatenate everything into a single file, which only happens if you use :simple or :advanced optimizations)

There is a pull request to provide a better error message but until then you have to be aware of these problems.

Example failures from all the runners:

Read the rest of this entry »

Posted in Languages, Testing | Tagged: , | Comments Off on Fixing clojurescript.test failing with “ReferenceError: Can’t find variable: cemerick”

How to create and run Gatling 2.0 tests

Posted by Jakub Holý on April 28, 2014

Getting up and running with Gatling perf. tests as I would like so I record this for my future reference.

0. Create a project:

$ mvn archetype:generate \
   -DarchetypeCatalog=http://repository.excilys.com/content/groups/public/archetype-catalog.xml
   -Dfilter=io.gatling:

(The trailing “:” in the filter is important.)

1. Import to IntelliJ

In IntelliJ choose to import an object, instead of “from sources” select “from external model” and then Maven. You will also need to have the Scala plugin installed and, when imported, you will likely need to right-click on pom.xml and Maven – Reimport.

2. Record a simulation

  1. Run the src/test/scala/Recorder.scala (right-click – Run ‘Recorder’)
  2. Set the port it should listen on, f.ex. 8000 (maybe you also need to set port for HTTPS, f.ex. 8001), set the target app (perhaps localhost, <some port>, <some https/dummy port>)
  3. Optionally set the class name of the recorded simulation and the target package (the output goes to src/test/scala/<package>/<name>.scala)
  4. Click [Start !]
  5. Go to your browser and configure it to use the recorder as its HTTP[s] proxy
  6. Browse localhost:8000/your_app as you want for the test
  7. Click [Stop and save] in the Recorder UI

Read the rest of this entry »

Posted in Testing, Tools | Tagged: , | Comments Off on How to create and run Gatling 2.0 tests

How To Generate A Valid Credit Card Number For A Bin (First 6 Digits)

Posted by Jakub Holý on March 25, 2014

There is plenty of generators that can produce numbers that are valid credit card numbers according to the Luhn check and specific rules of the individual issuer companies. However I have not found anything that would generate the missing digits given a bin, i.e. the first 6 digits of a credit card (the “bank identification number”). So I created one, reverse-engineering org.apache.commons.validator.routines.CreditCardValidator from common-validator 1.4:

// Groovy:
/** Map RegExp from C.C.Validator to the total length of the CC# */
binReToLen = [
        (~/^(3[47]\d{0,13})$/) : 13+2, // amex
        (~/^30[0-5]\d{0,11}$/) : 11+3, // diners 1
        (~/^(3095\d{0,10})$/) : 10+4, // diners 2
        (~/^(36\d{0,12})$/) : 12+2,     // diners 3
        (~/^|3[8-9]\d{0,12}$/) : 12+2,  // diners 4
        (~/^(5[1-5]\d{0,14})$/) : 14+2, // master
        (~/^(4)(\d{0,12}|\d{15})$/) : 12+1 // visa
        // Discover cards omitted
]

/** Bin is e.g. 123456 */
def completeCCn(String bin) {
    def ccnFill = "1" * 19
    int ccnLen = lenForBin(bin)

    def ccnWithoutCheck = bin + ccnFill[0..<(ccnLen - 6 - 1)] // - bin, - check digit

    def check = computeLuhncheckDigit(ccnWithoutCheck)

    return "$ccnWithoutCheck$check"
}

def lenForBin(String bin) {
    def match = binReToLen.find { it.key.matcher(bin).matches() }
    if (match == null) {
        throw new RuntimeException("Bin $bin does not match any known CC issuer")
    }
    match.value
}

def computeLuhncheckDigit(def ccnWithoutCheck) {
    org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit.LUHN_CHECK_DIGIT.calculate(ccnWithoutCheck)
}

completeCCn('465944') // => 4659441111118

Testing FTW!

Posted in General, Languages, Testing | Tagged: , | Comments Off on How To Generate A Valid Credit Card Number For A Bin (First 6 Digits)