Mer om språk och Ruby TDP007 Konstruktion av datorspråk Föreläsning 2 Peter Dalenius Institutionen för datavetenskap 2017-01-17
2 Översikt 1. Hur kan man bedöma ett språk? 2. Enhetstestning 3. Likhet i Ruby 4. Reguljära uttryck 5. Inför första seminariet
1. Hur kan man bedöma ett språk? 3 Exempel Historik Språk Verktyg Utvecklare Dokumentation
Hur skriver jag Hello World!? Hur ser syntaxen ut? Liknar språket något som jag redan kan? Vilka av de vanliga konstruktionerna finns och hur ser de ut? Vilka datatyper finns? Språk Vad är omfattningen på de kodbibliotek som följer med språket? Finns det någon speciell kodningsstil som används? Hur utbyggbart är språket? Kodbibliotek Språk Särskilda konstruktioner Baskonstruktioner Vad finns det för särskilda konstruktioner i det här språket som inte finns i andra språk? Finns det några särskilda sorters uppgifter som det här språket verkar lämpat för? 4
Verktyg 5 Hur kommer jag över huvud taget igång med att skriva och testa program? Språk Är språket interpreterateller kompilerat? Vilka utvecklingsmiljöer finns och vilket stöd ger de programmeraren? Hur funkar det med driftsättning av programvara som ska köras på riktigt? Utvecklingsmiljö Verktyg Körmiljö
Dokumentation 6 Vilken information om grundspråket finns (specifikationer, läroböcker)? Vilken information om kodbibliotek finns? Hur dokumenterar jag den kod som jag skriver själv? Finns det bra utbildningsmaterial tillgängligt (ex. tutorials)? Språk Verktyg Dokumentation Dokumentation Utbildningsmaterial
Utvecklare 7 Vem bestämmer hur språket ska se ut? Har språket en bred bas av aktiva utvecklare? Vilka är det som använder språket? Språk Verktyg Utvecklarcommunity Utvecklare Ägare Dokumentation
Historik 8 Historik Trender Bakgrund Hur länge har språket funnits? Hur stabilt är språket? Görs det drastiska ändringar fortfarande? Finns det olika implementationer? Vad var det ursprungliga syftet med att skapa språket? Talas det om språket? Vad har hänt den senaste tiden? Språk Verktyg Utvecklare Dokumentation
Exempel 9 Tillgängliga program Exempel Framgångsexempel Hur mycket används språket till verkliga projekt? Finns det några dokumenterade Språk framgångsexempel? Finns det fria exempelprogram eller öppen källkod-projekt? Historik Verktyg Utvecklare Dokumentation
10 2. Testning: Fyra nivåer Enhetstest (eng. unit testing) Varje enhet, t.ex. funktion, testas för sig. Integrationstest Test av flera enheter tillsammans. Systemtest Hela systemet testas, t.ex. säkerhet, prestanda, användbarhet. Acceptanstest Slutligt test av kunden.
11 Testning: Två strategier Black box test Den som utformar testerna har inte sett koden utan utgår från specifikationen. White box test Testerna baseras på analys av programkoden.
12 Enhetstestning Fördelar Underlättar förändring Underlättar integrationstestning Kan i viss utsträckning ersätta design och dokumentation Enhetstestning i Ruby Grundtanken är att vi paketerar testfall som kan köras automatiskt med hjälp av modulen Test::Unit Testfall är egentligen en uppsättning s.k. assertionseller förväntningar på utdata
13 Vad är det man ska testa? https://www.sempf.net/post/on-testing1.aspx
14 Exempel på enhetstestning Vi vill här testa funktionen faculty i filen faculty.rb. require './faculty' require 'test/unit' class TestFaculty < Test::Unit::TestCase def test_simple assert_equal(1, faculty(0)) assert_equal(1, faculty(1)) assert_equal(120, faculty(5)) assert_equal(2432902008176640000, faculty(20)) end end
15 Körning av enhetstester Alternativ 1: Köra direkt från kommandoraden (rekommenderas) ruby test_faculty.rb Alternativ 2: Vid prompten i irb(rekommenderas inte) require './faculty' require './test_faculty' require 'test/unit Test::Unit::Runner.new(TestFaculty).run Resultat av körning: Run options: # Running tests:. Finished tests in 0.008113s, 123.2628 tests/s 1 tests, 3 assertions, 0 failures, 0 errors, 0 skips
16 Några fler sätt att testa Det finns fler sätt att testa som man kan hitta i paketet Test::Unit::Assertions. Här är några exempel: assert(a<5) assert_equal(a, b) assert_not_equal(a,b) assert_nil(my_array) assert_nothing_thrown { do_stuff(a) } assert_in_delta(a, 100.0, 0.01) Testar uttrycket är sant Testar om a==b Motsatsen till ovanstående Testar om uttrycket är nil Testar att koden inte kastar några undantag Testar om a är inom intervallet Gå till www.ruby-doc.org, välj Standard Library API, leta upp paketet test/unit och klassen Test::Unit::Assertions. OBS! Från och med version 2.2 av Ruby är test/unit inte längre en del av standardbiblioteket, utan måste laddas ner separat.
17 Övning Hämta filerna faculty.rboch test_faculty.rbfrån föregående exempel från kurswebben (sidan med föreläsningar) och kör testet, bara för att se hur det funkar. Hämta också filen some_functions.rboch utforma lämpliga enhetstester för dessa funktioner.
18 3. Likhet i Ruby a == b testar om a och b är samma objekt. Flera klasser har egna definitioner av ==. Till exempel är 1 == 1.0 trots att det är olika klasser. Likhet beror alltså på klassen. För att alltid kunna jämföra objekt finns a.equal?(b) En svagare form av likhet a.eql?(b)används bl.a. av Hash för att testa likhet. a === banvänds bl.a. av case-satsen. Den är oftast samma som ==.
19 4. Reguljära uttryck vad är poängen? Den enklaste formen av formellt språk Används oftast för att söka efter mösnter i text Exempel: wildcards (*.txt) är en enklare form grep m.fl. vanliga Linux-kommandon tar reguljära uttryck scriptspråk, t.ex. Perl Det finns några olika uppsättningar, olika kraftfulla, en del till och med mer än riktiga reguljära uttryck
20 Reguljära uttryck i Ruby >> /be/ =~ "To be, or not to be..." => 3 >> /o+/ =~ "Moo mooo moooo!" => 1 >> "23, 18, 45" =~/1[0-9]/ => 4 >> /\w\d/ =~ "ABC123" => 2 >> /kul/ =~ "Inget roligt här!" => nil Testa gärna själv på rubular.com
21 Matchning av enskilda tecken Alla tecken utom \/^$.+*?()[]{}matchar sig själva. Dessa måste föregås av \om man vill matcha dem.. matchar ett godtyckligt tecken (alltså ett tecken, vilket som helst). [characters] matchar ett av de uppräknade tecknen. [aeiouyåäö] matchar en liten svensk vokal [a-za-z] matchar en engelsk bokstav, liten eller stor (två uppräkningar) [^characters] matchar ett tecken som inte ingår i uppräkningen Det finns genvägar för några klasser av tecken: \w matchar ett alfanumeriskt tecken \d matchar en siffra \s matchar ett white space
22 Sammansatta matchningar Om aoch bär två reguljära uttryck så gäller: ab matchar de två uttrycken efter varandra a bmatchar endera av aeller b a* matchar noll eller fler förekomster av a a+matchar en eller fler förekomster av a a{m} matchar exakt m förekomster av a a{m,} matchar minst m förekomster av a a{m,n}matchar mtill nförekomster av a
23 Förankring Det normala beteendet är att matchningen söker igenom texten från början till slut, men det finns undantag: ^och $matchar början respektive slutet av en rad \Aoch \zmatchar början respektive slutet av strängen \b matchar ordgränser (och \B är tvärtom)
24 Metoder som använder reguljära uttryck >> s = "The stars, like dust" => "The stars, like dust >> s.sub(/e/,'$') => "Th$ stars, like dust >> s.gsub(/[aeiouy]/,'*') => "Th* st*rs, l*k* d*st >> s.gsub(/(^, \s)\w/) { m m.upcase } => "The Stars, Like Dust >> s.split(/[\s,]+/) => ["The", "stars", "like", "dust"] >> s.scan(/[aeiouy]\w/) => ["ar", "ik", "us"]
25 Resultatet av en matchning >> /[aeiouy]{2,}/ =~ "the moon is a cheese" => 5 >> [$`, $&, $'] => ["the m", "oo", "n is a cheese"] >> /(\d\d):(\d\d):(\d\d)/ =~ "Klockan är 12:35:40 nu" => 12 >> [$1, $2, $3] => ["12", "35", "40"]
26 Resultatet av en matchning >> s = "the moon is a cheese" => "the moon is a cheese" >> re = /[aeiouy]{2,}/ => /[aeiouy]{2,}/ >> md = re.match(s) => #<MatchData:0xdf65ed4> >> [md.pre_match, md[0], md.post_match] => ["the m", "oo", "n is a cheese"] >> md2 = /(\d\d):(\d\d)/.match("14:45") => #<MatchData:0xdb94f94> >> md2.captures => ["14", "45"]
27 Övning Hitta på ett reguljärt uttryck som matchar en svensk postadress, t.ex. 584 31 Linköping. Finns det några postorter vars namn innehåller något annat än bara vanliga bokstäver? Baka in det i en funktion som svarar sant eller falskt, givet en sträng som kanske innehåller en postadress. Gör en testklass med lämpliga testfall. Ta även med negativa tester, dvs det reguljära uttrycket får inte matcha strängar som inte är postadresser. Testa reguljära uttryck i Ruby på rubular.com
28 5. Inför första seminariet Hur kan man sätta sig in i den andra gruppens kod med begränsad tid? Läs deras utvecklarblogg! Kör deras tester! Hur gör man en bra opposition? Om någon ska beskriva en lösning för dig, hur vill du att de ska göra? Tänk ut ett par frågor att ställa till gruppen. Utgå från frågorna som finns i anvisningarna för utvecklarbloggen. Lärde ni er något av gruppens lösning?
www.liu.se