söndag 20 augusti 2023
Windows 11 update hijacks the Print Screen button (from Lightshot)
onsdag 9 augusti 2023
Do you know the difference between a Fake, a Spy, a Stub, a Dummy and a Mock when writing unit tests?
Published at last
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
- Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
- Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.
The old draft
When you know the differences between the types, then you might want to read more about how to choose between them according to Mark Seeman here: Mocks for Commands, Stubs for Queries
In his post Mocks Aren't Stubs, Martin Fowler also explains the difference between stubs and mocks and investigates pros and cons of the classicist and mockist way of writing your tests.
So, something that I thought I already knew and I could write about in an hour or so, ended in hours of research and a post with links... keeping it DRY :)
lördag 5 augusti 2023
Skapa en AI-modell som styr en bil i AWS DeepRacer
AWS DeepRacer
Skapa en modell
Steg 1: Val av modellnamn och bana
I första steget får du namnge modellen och om du vill även ange en beskrivning av den.
Det finns 61 banor att välja mellan att träna modellen på.
Vågar man sig på att fälla ut "Hyperparameters" så blir det riktigt läskigt, men som tur var så var rådet att låta dessa vara tills man blivit varm i kläderna.
Steg 3: Definiera vad bilen kan göra, d v s dess Action space
Först får man lite info igen.
Sen ska man välja mellan "Continuous" eller "Discrete" action space.
Väljer man "Continuous" så kan man i nästa steg ange max styrvinklar och min/max hastighet.
Jag har testat att använda båda sorterna, men det var ett tag sen jag skapade mina modeller och minns inte om någon av dem fungerade bättre. Jag fick aldrig till läsningen av loggfilerna som skapas vid utvärderingen av modellen, men om man får det så verkar logganalysverktygen mer anpassade till (eller kanske t o m kräva) "discrete"-varianten.
Steg 4: Välja fordon
Jag har två likvärdiga virtuella bilar, den färgglada har jag för mig att jag fick som pris för att jag ställt upp med en modell i en tävling. Det finns varianter av bilarna, iallafall av de fysiska, som har dubbla framåtriktade kameror och LIDAR.
Steg 5: Belöningsfunktionen
Det är nu man får börja koda! Här ska du, i Python, ange den belöningsfunktion som modellen ska tränas med. Modellen får in bilens tillstånd, den tar ett beslut om vad bilen ska göra härnäst och din belöningsfunktion berättar för träningsalgoritmen hur bra beslutet var utifrån bilens nya tillstånd.
Nedanstående funktion är förifylld, den kan returnera fyra olika värden beroende på hur långt från mitten bilen är placerad, ju längre bort från mitten desto lägre värde. Det vill säga, den belönar modellen när den lyckas följa mittlinjen.
- "all_wheels_on_track"
Boolean
flag to indicate if the agent is on the track - "x"
float
agent's x-coordinate in meters - "y"
float
agent's y-coordinate in meters - "closest_objects"
[int, int]
zero-based indices of the two closest objects to the agent's current position of (x, y). - "closest_waypoints"
[int, int]
indices of the two nearest waypoints. - "distance_from_center"
float
distance in meters from the track center - "is_crashed"
Boolean
Boolean flag to indicate whether the agent has crashed. - "is_left_of_center"
Boolean
Flag to indicate if the agent is on the left side to the track center or not. - "is_offtrack"
Boolean
Boolean flag to indicate whether the agent has gone off track. - "is_reversed"
Boolean
flag to indicate if the agent is driving clockwise (True) or counter clockwise (False). - "heading"
float
agent's yaw in degrees - "objects_distance"
[float, ]
list of the objects' distances in meters between 0 and track_length in relation to the starting line. - "objects_heading"
[float, ]
list of the objects' headings in degrees between -180 and 180. - "objects_left_of_center"
[Boolean, ]
list of Boolean flags indicating whether elements' objects are left of the center (True) or not (False). - "objects_location"
[(float, float),]
list of object locations [(x,y), ...]. - "objects_speed"
[float, ]
list of the objects' speeds in meters per second. - "progress"
float
percentage of track completed - "speed"
float
agent's speed in meters per second (m/s) - "steering_angle"
float
agent's steering angle in degrees - "steps"
int
number steps completed - "track_length"
float
track length in meters. - "track_width"
float
width of the track - "waypoints"
[(float, float), ]
list of (x,y) as milestones along the track center
Avslutning
tisdag 4 juli 2023
Podcast-avsnitt som sammanfattar psykologisk trygghet bra
Rätt ut från utkast
Det här är ett inlägg som legat som utkast i över ett år. Det jag egentligen ville ha sagt då var just att
jag tyckte att det här avsnittet sammanfattade det (psykologisk trygghet) mycket bra och att det därför kunde vara bra att "spara" som ett blogginlägg
men genast började jag gräva i vad teal-podden och teal är och därför blev målet otydligt och inlägget aldrig klart. Nu släpper jag det som det är med det här lilla tillägget 😀
Intro
Hade nyss en fönsterputsardag och lyssnade då samtidigt på avsnitt 35 av tealpodden som handlade om psykologisk trygghet. Jag har hört, sett och läst om psykologisk trygghet från många källor nu, men jag tyckte att det här avsnittet sammanfattade det mycket bra och att det därför kunde vara bra att "spara" som ett blogginlägg.
Om Tealpodden och vad är teal?
Tealpodden hittade jag för att Ulla Osterman, upphovsmakaren till dialogverktyget Orangino Work, delade det Tealpodd-avsnitt där hon var med och pratade om sitt dialogverktyg. Tealpodden drivs av Fredrik Högström och Maria Berglund:
Vi driver Tealpodden som en hobby, vid sidan av våra vanliga jobb. Idén till Tealpodden kom under en långpromenad. Vi hade läst boken Reinventing Organizations och tyckte att den satte fingret på något vi båda känt och försökt formulera – att ett bättre, snällare och mer livstillvänt arbetsliv var möjligt. Men hur kunde vi bidra till den förändringen? Jo, vi startar en podd! En podd där vi utforskar framtidens organisationer och hur en annorlunda arbetsvardag kan se ut.
![]() |
| Fredrik Högström och Maria Berglund https://www.tealpodden.se/om-oss/ |
Teal är en färg mellan blå och grön och har fått sitt namn från det engelska ordet för fågeln kricka, som har färgen som ett band bakom ögat. Det var standardfärgen på skrivbordet i Windows 95.
![]() |
| https://commons.wikimedia.org/wiki/File:Corhwyaden.jpg |
Fredric Laloux, författaren till Reinventing Organizations, kopplar färger till organisationers mognadsstadier och använder teal till det högsta stadiet.
![]() |
| https://prominda.com/english/teal-organizations/ |
Om podcast-avsnittets gäster
I avsnittet om psykologisk trygghet så gästas Tealpodden av Maria Wigenius och Lina Hedin från Add Insight som arbetar med att bygga psykologisk trygghet i team och organisationer.
![]() |
| Maria Wigenius och Lina Hedin https://www.tealpodden.se/podcast/avsnitt35/ |
onsdag 28 juni 2023
Gästat annat team för en Orangino Work-session
Bakgrund
Torsdagen den 15:e juni 2023 blev dagen då jag för första gången höll i en Orangino Work-session i ett annat team än mitt eget. Anledningen till att jag skriver det här inlägget är för att senare komma ihåg hur det var och tankar kring vad jag kan ändra på till en eventuell nästa gång. Om du som läser det här inte har koll på vad Orangino Work är så är det nog svårt att hänga med, men du vill kan du läsa min intro här.
Teamet som bjöd in mig är ett "kusinteam" till det jag ingår i och hade tidigare kört en omgång själva efter en mycket kort överlämning mellan mig och teamledaren. Anledningen till att jag blev inbjuden var för att teamledaren skulle kunna fokusera helt på att bara vara deltagare och för att se om det var några signifikanta skillnader i hur vi leder en session. Det här var en del av deras återblick (retrospective) de körde den eftermiddagen.
Upplägg
- "Hur ska jag tänka kring skattningen för teamet? Är det hur vi är överlag inom teamet, eller är det hur teamet är mot andra team?"
- "Jag förstår inte beteendet eller beskrivningen riktigt, vad ska jag göra?"
- Ber om hjälp
Jag vågar be andra om hjälp i mitt arbete när så behövs - Lyhörd
Jag är bra på att uppfatta även sådant som inte är tydligt uttalat. - Pålitlig
Jag står för de utfästelser jag gör. - Nätverkare
Jag bygger ständigt mitt eget nätverk som ett led i att skapa nya möjligheter. - Läraktig
Jag har vilja och förmåga att lära mig nya saker.
- "Vad har du lärt dig under sessionen?"
- "Har du nån feedback till mig att tänka på om jag gör det här igen?"
Feedback från deltagarna
Egna reflektioner
- beteendets betydelse för gruppen,
- vilka beteenden där gruppen har störst/minst samstämmighet,
- vilka beteenden som väckte störst engagemang och energi
- Kom alla till tals lika mycket?
- Hur var öppenheten?
- Lyssnade vi på varandra?
Är det här nåt jag vill göra igen?
lördag 3 juni 2023
Började skriva en Lisp-interpretator i C#
Det här inlägget ska klargöra, (för dig, men också för mig själv), varför jag började försöka skriva en Lisp-interpretator i C# och hur långt jag kommit hittills.
Mycket kort Lisp-introLisp är ett gammalt programmeringsspråk, det specades 1960 och är det näst äldsta högnivåspråket som fortfarande används (Fortran är äldst). Namnet är ett sammandrag av LISt Processing. Det finns många dialekter av språket, där de mest kända är Common Lisp, Scheme, Racket och Clojure.
Nåt som gör att Lisp ser en aning egendomligt ut är att uttryck avgränsas av parenteser och att det är prefix-noterat. Att skapa en variabel och binda det till värdet av en beräkning kan i ett krystat exempel i C# se ut såhär:
int x = 1 + 2;
I Lisp skrivs det såhär:
(define x (+ 1 2))
Prefix-notationen innebär att operatorn kommer först i ett uttryck och sen dess argument. Det kan se lite avigt ut när man är van med annat.
Varför är "list" en del av Lisps namn då? Jo, programkoden utgörs av listor, som byggs upp av enkellänkade par. Uttrycket ovan representeras internt med den här strukturen:
Hur jag kom i kontakt med LispNär jag började på högskolan i Linköping så möttes man, som jag minns det, av en mängd mattekurser. När man tagit sig igenom dem, så var det äntligen dags att programmera! Men mycket snart upptäckte vi att det skulle göras i gamla dammiga Common Lisp 😱 När det fanns C++ och Java?!? Men, det var nog vettigt, det gav förståelse för att programmeringsspråk är verktyg som har olika styrkor och svagheter och att inte fastna för mycket i ett enda. Jag kan dock inte påstå att jag har använt just Lisp utanför skolan än.
Så, varför skriva en egen interpretator?Resultat hittills
Uppdelning i lexer, parser och evaluator
Parser
- Självevaluerande uttryck.
Bool och nummer, ska nog lägga till sträng-hantering med. - Variabeluppslag
- Tilldelning av värde till variabel
- If
- Uttryck
Just nu endast +, - och specialformerna and och or.
(Ett vanligt uttryck evaluerar alla argument, en specialform evaluerar bara de argument som behöver evalueras.)

söndag 6 februari 2022
Gherkin - det gemensamma "språket" från produktägare till utvecklare
Gherkin
Jag har nu haft möjligheten att använda Gherkin på jobbet, ett språk, eller kanske mer en mall, som används för att skriva systemtest så att de ska bli läsbara och förståeliga hela vägen från produktägare till utvecklare. Vi är bara i början av resan, men det verkar mycket lovande och intressant! Rekommenderar!
Om du är som jag och undrar varför saker heter som de heter så kan jag avslöja att gherkin betyder "liten picklad gurka". Och språket Gherkin används i testramverket Cucumber, vilket frun till skaparen fick namnge:
My wife suggested I call it Cucumber (for no particular reason), so that's how it got its name. I also decided to give the Given-When-Then syntax a name, to separate it from the tool. That's why it's called Gherkin (a small, pickled Cucumber).
Cucumber är ett Ruby-ramverk, sitter du med .net så är det SpecFlow som gäller om du vill skriva test med Gherkin.
För att du ska få en känsla för hur språket ser ut så kommer här ett exempel, där de fetkursiva orden, samt möjligheten till den korta beskrivningen på raden under scenario, tillhör Gherkin:
Scenario: Duplicate email
Where someone tries to create an account for an email address that already exists.
Given I have chosen to sign up
But I enter an email address that has already registered
Then I should be told that the email is already registered
And I should be offered the option to recover my password

Godbitar jag hittat
För att komma in i testskrivandet lite snabbare så läste jag The Cucumber Book - Behaviour-Driven Development for Testers and Developers. Här nedan kommer de partier jag markerat som "kom ihåg" under läsning.
Readability
System tests Vs unit tests
It's also worth thinking about whether some of the behavior you've specified in Cucumber scenarios could be pushed down and expressed in fast unit tests instead. Teams that enthusiastically embrace Cucumber sometimes forget to write unit tests as well and rely too much on slow integration tests for feedback. Try to think of your Cucumber scenarios as broad brush strokes that communicate the general behavior of the code to the business, but still try to get as good a coverage as you can from fast unit tests. Help make this happen by having testers and programmers work in pairs when implementing Cucumber scenarios. This pair can make good decisions about whether a piece of behavior necessarily needs to be implemented in a slow end-to-end Cucumber scenario and drive out the behavior using a fast unit test instead.Överflödiga detaljer
When Cucumbers Go Bad: Imperative Steps
It's true that using declarative style will mean you have to write more step definitions, but you can keep the code in those step definitions short and easy to maintain by pushing the actual work off into helper methods in your support code.





































