Showing posts with label unit test. Show all posts
Showing posts with label unit test. Show all posts

Friday, May 12, 2017

Maximum Score - Rookie 3 (II)

May 12, 2017

Introduction 


It is a good idea to continue to work on maximum score algorithm, and also ask a question on code review. Learning memoization and bit mask is not an easy task, also Julia likes to learn the time complexity analysis algorithm better through the study.

Julia wrote a blog to document her learning experience on the algorithm, from the contest performance to after-contest catching up.


Code review preparation 



C# code in the contest is here. Score 3.5 of 35 points. 

May 12, 2017 11:16 pm 

Code review of C# code in the contest, and then move the memoization out-of-for-loop, scored 10.50 of 35 points. C# code is here.


Memoization Analysis Challenge


Instead of going over the recurrence formula, Julia likes to use an example to explain what can be in memoization. And what is her mistake in the contest? What is the reason causing the false analysis?

Suppose that the array has two numbers, int[] numbers = new int[]{1, 2}. The problem is to find the maximum sum such that the order of two numbers to put into scoring make the value maximum.

What is the subproblem of max score?

Guess what is the subproblem


May 13, 2017 11:03pm

First, add sum of the array. The array new int[]{1, 2}'s sum is 3.

To choose the last number, two options, either 1 or 2. If the last number is 1, array's index is 0, then the 0th score is (3 - 1) % 1 = 0. Next number is 2, sum is 0, and then the 1th score is 0 % 2 = 0. The sum of score values (0th, 1th) is 0.

In other case, if the last number is 2, array's index is 1, then the score is (3 - 2) % 2 = 1. Next number is 1, sum is 0, and then 0 % 1 = 0. The sum of score values is 1.

From the above two cases, the maximum score is 1 by taking 2 as last number and then taking 1 as the first number. Just remind friendly that the order is opposite from end to start.

The maximum value is to choose maximum value from a set with two values.

The memoization process is to record to Dictionary<string, int> calculated.
["0", 1]
["1", 0]
["", 1]


One more test case 


Suppose that the array has two numbers, int[] numbers = new int[]{1, 2, 1}.

Calculated variable as Dictionary<string, int> has the following:
[0 1, 0]
[0 2, 0]
[0, 1]
[1 2, 0]
[1, 0]
[2, 1]
[,1]

Debug the code, and check how many times the dictionary is looked up. 3 times.
key = "0 1", "0 2", "1 2".

Draw a recursion tree for this simple test case. Here is the graph:

Argument: If you can work on this simple test case and also work out the recursion tree correctly, then I believe that you can solve the problem using memoization and recursive, DP solution correctly as well.


Common advice




Do not memo one more item in one recursive call; Stay outside the for loop; Memo before return statement.

Julia, if you are very good at unit testing, and work on simple and very good test case in the design of algorithm, your performance on Hackerrank can improve at least 20%.

Make it all


It is the first challenge Julia worked on since last January on hackerrank, on the topic of bit mask, dp, memoization, subset. So she likes to make the algorithm everything. Learn one algorithm a time. Do not rush.

Julia likes to review a list of things on the algorithm. Bit mask, memoization, time complexity analysis.

Use bit mask, the code passes all test cases. 
C# practice code is here.


Hackerrank Editorial Notes


In order to write a good question on code review, Julia also have to write down some notes from editorial notes from hackerrank on the maximum score algorithm.

Here is the link of editorial notes.

Julia's note:
time complexity: O(2n * n)

Recursion tree - a major flaw, same recursive call many times; It results in exponential running time.


Actionable Items


Read book "Testable JavaScript" and then figure out a few things I can do in order to have a good sense of setting up test cases to help Hackerrank contest.

The algorithm is also on code review.stackexchange.com, the link is here.


Sunday, November 8, 2015

testing, automation and testing patterns

Nov. 8, 2015

  Watch the video:

Automated Testing Patterns and Smells

 https://www.youtube.com/watch?v=Pq6LHFM4JvE

Julia is a developer in the city of Vancouver last 5 years, she enjoyed the understanding how to minimize time 70% by following one simple principle: DRY - Do not repeat yourself.

For instance, to calculate something, the same code repeats twice; Just a simple example, Julia does not like to see the code repetition in the C# code, so she gives out a try to use base class, and then, merge to one function applying to the base class. But, all other repetitions are everywhere, so she cuts other places similar to the one, 2 to 1. So, do a math, the code needs change for cases 2 x 2 x 2, 3 place duplication, becoming 1 x 1 x 1; Done, reduce the 7/8 work to work with design, unit test, and bugs related to design. (similar ideas seen video, watched on Nov. 13, 2015 - https://www.youtube.com/watch?v=bxQK7hcVyGs&list=PLD4GnSXHpkQ2_eKG5fKzszXs5hYcEsft7)

Julia tries to contribute the ideas to show how important it is to following DRY principle, and then, reduce test cases, improve code quality, and then, shorten time to work on a project.

Back to the video, Julia likes to write down the notes from the video, she does not have time to read 600 pages book, but she knows the tip: get a good video, google talk, and then, invest 2-3 hours:

1. video time 16:07/59.33
What is a " Test smell"
1. duplicate code, hard coded values, etc.

A set pf symptoms of an underlying problem in test code. Like duplicate code, breaking DRY principle.

In the talk, using changing diaper as an example, how to know when to change diaper? When diaper stinks.

code smells - visible problems in test code
behavior smells - test behaving badly
project smells - testing-related problems visible to a project manager

2. video time 19:27 / 59:33
What's a "Test Pattern"?

A "test pattern" is a recurring solution to a test automation problem
- E.g. A "Mock Object" solves the problem of verifying the behavior of an object that should delegate behavior to other objects

Test Patterns occur at many levels:
- Test automation strategy pattern
 recorded test vs scripted test
- Test design Patterns
 implicit setup  vs delegated setup
- Test coding patterns
  assertion method, creation method
- Language-specific test coding idioms
  expected exception test, constructor test

3. video time 20:28/59:33
Common code smells
  • conditional test logic
  • hard to test code
  • obscure test
  • test code duplication 
  • test logic in production 
4. Example to explain, best part
video time 22:16/59:33

1. Better assertion
2. Hard-wired test data - what is the relationship between those data? What is math? Do we need math? 30, why it is not 1, 19.99, why it is not 2, 69.96, why it is not 3? 6 months later, what is business logic?
    Hard-wired test data - will lead to fragile test

3. Introduce custom assert

  Avoid any conditional test logic in the test method - make less test code.
  Problem of conditional test logic is not sure what you are testing. <-  Julia likes this argument
  use customer assert, make a compaction of the code.

video time 28:58 / 59:33
4. Automated fixture teardown

tear down logic is a smell, such as, to separate business logic with presence logic

explicitly create deleteAllTestObjects instead of those complicated logic checking - nested try methods.

5. video time 32:07 / 59:33
Obscure test - irrelevant information

create address
create ..                               vs   createAnnoymousCustomer       vs createAnnoymounsInvoice
create customer                         createAnnoymounsInvoice

Hide detail in creation method - encapsulation, what is level of info - different levels info stays in one function - create more functions - each function much easy to be understandable, easy for unit test, variable scope less than a few lines

6. Test coverage, rapid test writing

Work outside in, create functions not existed yet, type test what you like to look

- Julia's comment:
If the code she wrote, it seems that the task is not showed in Leetcode questions, that means the code is not abstracted, not using object-oriented programming, cannot be unit test easily, people cannot read it without too much memorization, one function does all kinds of tasks; results? just too much time wasted for development, maintenance, testing, and it is bad behavior, not a pro. 


7. video time
44:08/ 59:38
Reducing Erratic Tests - Shared Fixture

Build new Shared Fixture for each run
- Avoids Unrepeatable Tests
- When:
 >> Lazy Setup
>> Setup Decorator
>> SuiteFixture Setup

Fragile Tests:
Causes:
Interface Sensitivity
- Every time you can change the SUT (S- , U- , T- tear down), tests won't compile or start failing
- You need to modify lots of tests to get things "Green" again
- Greatly increases the cost of maintaining the system

Behavior Sensitivity
- Behavior of the SUT changes but it should not affect test outcome
- Caused by being dependent on too much of the SUT's behavior.

Data sensitivity

Context sensitivity
- something outside the SUT changes
e.g. system time/date, contents of another application

46:19/ 59:33
Hard to test code
. code can be hard to test for a number of reasons:
- too closely coupled to other software
- No interface provided to set state, observe state
- Only asynchronous interfaces provided

. Root cause is lack of design for testability
- comes naturally with Test-Driven development
- Must be retrofitted to legacy (test-less) software

. Temporary workaround is Test Hook
- Becomes test logic in production (code smell) not removed.

50:17/59:33
What Does it take to be successful?
Programming Experience
+ xUnit Experience
+ Testing Experience
+ Design for Testability
-  Test smells
+ Test Automation Patterns
+ Fanatical Attention to Test Maintainability

read the website:
http://xunitpatterns.com/

Julia's comment:
Source code should be only written for machine to understand             - 20%
Source code should be readable for herself after 6 months / years        - 20%
Source code should be minimal - DRY principle - All other principle for easy to understand,
relax for herself - any time                                                                     - 30%
Source code should be fun to read, with documented unit test cases, log history etc.                                           - ?


Sunday, October 25, 2015

Study notes - "The clean code talks - 'Global State and Singletons' "

10/25/2015

Google talks:

The clean code talks - "Global State and Singletons"

https://www.youtube.com/watch?v=-FRm3VPhseI

Global state:

 Julia tries to understand global state in this talk:

 Run same thing a multiple time, will get different test results;

 5:40/54:08
A. Multiple Executions can product different results
1. Flakiness
2. Order of tests matters
3. Can not run test in parallel

B. Unbounded location of state

C. Hidden Global State in JVM
    1. System.currentTime()
    2. new Date()
    3. Math.random()

D. Testing above code is hard
  1. Therefore inject in doubles

8:49/54:08
Singleton: Good vs Bad

1. Application Global vs. JVM Global
2. Usually we have one application per JVM
    A. Hence we incorreclty assume that:
         Application Global state = JVM Global

3. Each test is a different configuration of a portion of our application

19:01/54:08
Deceptive API
1. API that lies about what it needs
2. Spooky action at a distance

Julia's comment, the talk is interesting and worth time to watch again later.




The clean code talks - unit testing

10/25/2015

Watch the google talk "The clean code talks - unit testing", write down notes and then learn better for next time.

  video link:
  https://www.youtube.com/watch?v=wEhu57pih5w

Video time:
02:02 / 32:07
Hard to test code

Most People say:
Make things private
Using final keyword
Long methods

Real issues:  (interview questions)
Mixing new with logic
Work in constructor
Global state
Singleton
Static Methods   (procedure programming) (leaf method vs way-up method)
Deep inheritance (Divorce myself from inheritance at run time. )
Too many conditionals ()


Procedure code - Seam - Polymorphism - Julia's comment: look into it, read more about it. 10/25/2015

Video time:
 14:35/32:07
Progression of Testing:

1. Scenario / Large Tests
  Test whole applicatio by prentending to be a user
  slow / Flaky / Mostly happy paths

2. Functional / Medium Tests
  External dependencies simulated
  Test class interaction

3. Unit / Small Tests
    Focus on application logic
    Very Fast / No I/O / No Need for a debugger

4. Think of it more as a continuum than discrete

5. All tests levels important
    Not all levels have the same probability of a bug
    Because smaller tests cover less need more of them

6. Testability more important as you get more focused

Video time:
17:05 /32:07
Different kinds of Tests
Execution time :
unit test -> Functional Tests -> Scenario

Test individual  ->
Test collections of classes as subsytems ->
Test the whole system pretending to be a user

Video time:
27:06/32:07
How do you write hard to test code?

You mix object creation code with business logic
This will assure that a test case never can construct a graph of objects different from production. Hence nothing can be tested in isolation.

Unit test class -
Seam - friendly - try to understand the dependency injection
class depends on a lot of other classes, mocking, seam, learned through hacking,

class:
object graph
construction & lookup
business logic

27:36/32:07
Take Away
 Unit tests are a preferred way of testing

 Unit tests require seperation of instantiation of object graph from business logic under test

Questions:
1. Global variable - make test unpredictable, the order of test matters and so on and so forth.

    Do not clean up after yourself, another test will fail;
    Counter argument: framework than DI framework.

    Monkey-patching - evil on the global state - dependency injection

    C++ / Java / frameworks - dependency injection difference

And read the slideshow using the following link:

http://www.slideshare.net/avalanche123/clean-code-5609451

http://misko.hevery.com/code-reviewers-guide/

http://misko.hevery.com/presentations/

http://misko.hevery.com/2008/10/21/dependency-injection-myth-reference-passing/