Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Vincit Teatime 2015 - Niko Kurtti: Case Shopify: SaaS:n testaaminen, mihin unohtui toinen puolikas?

849 views

Published on

Lähes jokaista nykyaikaista ohjelmistoa testataan ennen kuin muutokset viedään käyttäjän saataville. Ohjelmiston käyttäjälle tarjoavaa alustaa nykypäivän DevOps-Cloud-InfraAsCode -hype maailmassakaan ei kuitenkaan usein testata samalla innolla. Vastaukset oleellisiin kysymyksiin kuten "katkeavatko käyttäjän yhteydet" tai "onko split brain mahdollinen" jäävät usein pintapuoliseen manuaaliseen koittamiseen. Infrakoodia voidaan kuitenkin testata ja kokonaisiin järjestelmiin kohdentaa järjestelmätestausta. Aivan kuten ohjelmistokehityksessäkin, oma paikkansa on myös tutkivalla testauksella. Tuotannossa, tottakai.

Published in: Technology
  • Be the first to comment

Vincit Teatime 2015 - Niko Kurtti: Case Shopify: SaaS:n testaaminen, mihin unohtui toinen puolikas?

  1. 1. SaaS testaaminen Miksi testata vain puolet?
  2. 2. Shopifacts • Alunperin pelkkä verkkokauppa-alusta, nykyisin tarjoaa myös mahdollisuuden kivijalkamyyntiin. • 150k kauppiasta, mm. Tesla, Github, LA Lakers, Wikipedia, Kith,... • 300k RPM+, flash sales >1M RPM • Ruby on Rails, MySQL, Redis, Memcache, Elasticsearch, Chef, Go, Podding, Multi-DC,...
  3. 3. Downtimeen ei ole varaa
  4. 4. Muutos on tästä huolimatta jatkuvaa Pelkästään Shopify core deployataan kymmeniä kertoja päivässä. Infrakoodia / muutoksia tämän lisäksi myös tusina+ päivässä Ympärillä olevia sovelluksia kymmeniä, teema/sovelluskaupat, julkiwebbi, kuvaskaalain, maksujärjestelmä, jne...
  5. 5. Testauksesta
  6. 6. Ohjelmistokehityksessä arkipäivää Moderniin kehitykseen kuuluu oleellisesti vähintäänkin yksikkötestaus ja integraatiotestaus CI-järjestelmässä. Tämän lisäksi löytyy pitkälle kehitettyjä menetelmiä ja sovelluksia aina koodianalyysistä suorituskykytestaukseen. ..puhumattakaan TDD/BDD -leiristä Testaaminen on oletusarvo, ei poikkeus
  7. 7. Esimerkki Java-ohjelman testaamisesta Ennen pushia: - Koodianalyysi, Findbugs - Yksikkö/integraatiotestaus, JUnit Ennen deployta tuotantoon: - Järjestelmätestaus, Selenium - Suorituskykytestaus, JMeter ( - Manuaalinen hyväksymistestaus )
  8. 8. Testaus infrapuolella Ennen pushia: - Mikä versiohallinta..? Ennen deployta tuotantoon: - Luin Googlen viidennestä hitistä että näin se toimii ja kävin manuaalisesti testaamassa Tai vaihtoehtoisesti: Käyttöpalvelutarjoaja vastaa tästä osuudesta
  9. 9. Mutta me tehdään devopsia agilesti? Vihjeellisissä yrityksissä käytössä CM tuotantoympäristöissä jotka jollain tavalla kiinni versiohallinnassa. Ohjelmistokehittäjillä Vagrantit, Dockerit, Ansiblet ja devopsreactions auki selaimessa Hyvistä lähtökohdista huolimatta inframuutoksien testaus kuitenkin harvinaista ja kevyttä happy case testausta omalla työasemalla.
  10. 10. Jos sammutan tämän koneen niin tuo toinen varmaan palvelee? Joo, näinhän se teki kun selaimessa F5:sta kliksuttelin — Senior Enterprise Devops Fullstack Consultant Architect
  11. 11. Päätökset tuotantoon liittyen useimmiten mututuntumalla Googlen viides hitti, kaveri ja näin tämä edellisessäkin projektissa toimi. Ei syvällistä ymmärrystä ratkaisujen toiminnasta tai vaikutuksista. ...istuntojen tila, inflight requestien kohtalo, käyttäjälle palautuvat ilmoitukset, MTTR jne
  12. 12. Onko täydelliselläkään koodilla arvoa jos käyttäjät eivät voi siitä hyötyä?
  13. 13. Infratestauksen mahdollisuudet Ennen pushia: - Koodianalyysi, Foodcritic - Yksikkö/integraatiotestaus, Chefspec/Serverspec/Test kitchen Ennen deployta tuotantoon: - Järjestelmätestaus, Minitest - Suorituskykytestaus, mysqlslap, memaslap, redis-benchmark jne. ( - Manuaalinen hyväksymistestaus )
  14. 14. Koodianalyysi, Foodcritic Koodianalyysityökalu Chef cookbookeille Todellinen arvo omissa säännöissä Shopifylla cookbooks repossa 130 contributoria, joten mahdoton varmistua, että kaikki ovat tietoisia kaikista käytännöistä luontaisesti Kevyt ajaa, ideaalinen integroida esim pre-commit hookkiin Gitissä
  15. 15. rule 'SHOP003', 'Individual email address used; prefer team email addresses' do tags %w{style recipe shopify} cookbook do |path| whitelist = %w(ops admins data-engineering database stack-team ) recipes = Dir["#{path}/{#{standard_cookbook_subdirs.join(',')}}/**/*.rb"] recipes += Dir["#{path}/*.rb"] recipes.collect do |recipe| File.readlines(recipe).collect.with_index do |line, index| if line.match("^((?!#{whitelist.join('|')}|#).)*@shopify.com") { :filename => recipe, :matched => recipe, :line => index+1, :column => 0 } end end.compact end.flatten end end
  16. 16. Chefspec (yksikkötestaus) Testaa Chef :n tekemiä muutoksia muistinvaraisesti CM -työkalut odottavat tietynlaisen tilan (lähtötila tai nykyinen) kun muutoksia ajetaan. Lokaali työasema ei yleensä samassa tilassa palvelinten kanssa. Tarjoaa perinteisen tarkan yksikkötestaamisen, mutta tilallisuuden vuoksi vaatii paljon vaivaa arvojen mockkaukseen. Vaikea myöskään pitää mockkeja ja palvelinten tiloja synkassa.
  17. 17. execute "maybe-convert-btrfs-to-overlay" do only_if 'stat -c%T -f /u|grep btrfs' notifies :create, 'cookbook_file[/opt/convert-btrfs-to-overlay]', :immediately end ☁ cookbooks [master] stat -c%T -f /u stat: illegal option -- c usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...] stat on eri työkalu OSX:llä kuin Linuxilla. Eikä /u ole tietysti edes olemassa saati BTRFS omalla Macbookilla...
  18. 18. context 'btrfs to overlay' do before(:each) do stub_command("stat -c%T -f /u|grep btrfs").and_return(true) end it 'trigger btrfs conversion to overlay' do expect(chef_run).to run_execute('maybe-convert-btrfs-to-overlay') end end Mitä tässä testataan? Jos ainoa järkevä testattava asia ( stat -c %T -f /u|grep btrfs ) mockataan mikä arvo jää testille? Your mileage may vary, Chefspec on todella näppärä apu inhimillisten one-off/typo/if-unless tyyppisten virheiden huomaamiseen
  19. 19. Integraatiotestaus - Test Kitchen/ Serverspec Integraatiotestauksen ero yksikkötestaukseen on se, että yksittäisten ehtojen sijaan testataan tilaa. Test kitchenissä integraatiot Vagrant, AWS, Docker ja tuki mm. RSpeccille ja Serverspeccille Järkevää integroida samaan CI-järjestelmään jossa sovellus
  20. 20. describe 'Base Packages' do %w( curl ... ).each do |package_name| describe package(package_name) do it { should be_installed } end end end describe 'nginx status' do it 'enables the nginx service' do expect(service 'nginx').to be_enabled end it 'starts the nginx service' do expect(service 'nginx').to be_running end it 'is listening on port 9005' do expect(port 9005).to be_listening end end describe nginx_version_is_correct(nginx_version) do its(:exit_status) { should eq 0 } its(:stdout) { should match(/nginx version: nginx/1.7.9/) } end
  21. 21. Järjestelmätestaus, Clusterfuck, Hyvin yksinkertainen kehikko halutun kokonaisuuden (esim. HA klusteri) testaamiseen. Fokus toiminnallisuudessa, ei tietyn työkalun toiminnassa. Esim vastaako palvelu requestiin eikä tekikö Chef muutoksen, tai onko palvelu x käynnissä. • Vagrant - ohjaa virtuaalikoneita/containereita ja provisiointia • Minitest - testaus • Raketaskit + hieman Rubyliimaa - helperit
  22. 22. Vagrantfile DNS-rekursoreita varten # DNS recursors clusters["dns"].size.each do |i| machine = clusters["dns"].machines["dns#{i}"] config.vm.define machine.id, primary: false do |config| initialize_machine(config,machine) config.vm.provision :chef_solo do |chef| set_cookbook_dirs(chef) # 1,2 are recursors, 3 just a normal node if i > 2 chef.add_role "vagrant-dns-client" else chef.add_role "vagrant-dns-recursor" end end # dont overwrite resolv.conf with dhclient preserve_resolv = <<-EOF echo 'make_resolv_conf() { : ; }' > /etc/dhcp/dhclient-enter-hooks.d/zzz-preserve-resolv-conf chmod +x /etc/dhcp/dhclient-enter-hooks.d/zzz-preserve-resolv-conf EOF config.vm.provision "shell", :inline => preserve_resolv end end
  23. 23. Esimerkkitestejä def setup @io_ip = host_dns_lookup('shopify.io') @com_ip = host_dns_lookup('shopify.com') for i in 1..CLUSTERS['dns'].machines.size start_pdnsd('start', "dns#{i}") flush_cache("dns#{i}") end assert_equal @io_ip, test_dns('shopify.io') end def test__outgoing_dns_block assert_equal @io_ip, test_dns('shopify.io') #warm cache for shopify.io begin block_dns_outgoing('dns3') do assert_equal @io_ip, test_dns('shopify.io') #test cached record refute_equal @com_ip, test_dns('shopify.com') #test record that is not cached end end assert_equal @com_ip, test_dns('shopify.com') #test that upstreams work after block end
  24. 24. Esimerkkejä helpereistä def test_dns(name, machine='dns3') `#{ssh_command(machine)} -- "ruby -e "require 'socket'; puts Socket.getaddrinfo('#{name}', 80)[0][3]""`.chomp end def pdnsd_service(cmd, machine) `#{ssh_command(machine)} -- "sudo /etc/init.d/pdnsd #{cmd}"` end def block_incoming_traffic(machines, &block) begin machines.each do |machine| block_traffic(machine, "53") end yield ensure machines.each do |machine| open_traffic(machine, "53") end end end def iptables(machine,port,direction, action="-D") ['tcp', 'udp'].each do |proto| ['eth0', 'eth1'].each do |interf| `#{ssh_command(machine)} -- sudo iptables #{action} #{direction} -p #{proto} --dport #{port} -o #{interf} -j DROP >& /dev/null` end end end
  25. 25. Kertauksena Findbugs <--> Foodcritic JUnit <--> Serverspec/RSpec Järjestelmätestaus <--> Minitest + liimaa Lisäpisteitä: - SCM -integraatiot (git hookit jne) - CI-integraatiot
  26. 26. Mikä unohtui?
  27. 27. Järjestelmätestaus sovelluksen näkökulmasta http://www.shopify.com/technology/16906928-building-and- testing-resilient-ruby-on-rails-applications Toxiproxy ( https://github.com/Shopify/toxiproxy ) Simuloidaan alla oleva infraa ja sen ongelmaskenaarioita. Ei ota kantaa toteuttaviin teknologioihin (TCP-proxy) Testit osana sovelluksen testisuitea
  28. 28. test "reconnects on next request after a connection timeout" do old_connect_timeout = ActiveRecord::Base.connection_pool.spec.config[:connect_timeout] assert old_connect_timeout begin ActiveRecord::Base.connection_pool.spec.config[:connect_timeout] = 2 ActiveRecord::Base.clear_all_connections! duration = Benchmark.realtime do assert_statsd_increment("Shopify.mysql.connection_error") do assert_raise(Mysql2::Error) do Toxiproxy[:shopify_test_mysql_master].downstream(:latency, latency: 5000).apply do Sharding.master_connection end end end end assert duration.between?(2, 4) assert_equal 1, Sharding.master_connection.select_value("SELECT 1") ensure ActiveRecord::Base.connection_pool.spec.config[:connect_timeout] = old_connect_timeout ActiveRecord::Base.clear_all_connections! end end
  29. 29. Game Day Otetaan tutkittavaksi yksittäinen osa palvelusta, esim. Elasticsearch -klusteri tai tietovarastot. Tarkoituksena löytää tutkittavasta kokonaisuudesta vikoja ja erityisesti ymmärtää miten oma palvelu käyttäytyy vikatilanteissa. Käytännössä toimii parhaiten mutujen ja oletuksien rikkojana (kahvat, timeoutit, kapasiteetti, palautumisnopeus, palautetut ilmoitukset jne.)
  30. 30. Game Dayn perusteet Game day on järkevintä suorittaa yhdessä tilassa ja riittävästi aikaa (4-8h) varaten. Paikalle kannattaa kutsua n. 6-12 henkilöä esim seuraavalla jaolla: • Järjestelmän parhaiten tuntevat (dev/ops/devops/opsdev) • Järjestelmästä kiinnostuneet ja/tai sen kanssa välillisesti työskentelevät Dedikoitu fasilisaattori helpottaa tilaisuuden läpivetoa sekä purkua.
  31. 31. Aloitus 1. Piirtäkää yhdessä karkea arkkitehtuurikuva järjestelmästä (riippuvuudet, toimijat jne.) 2. Keksikää yhdessä mahdollisia failureskenaarioita, kone kaatuu/verkossa ongelmia jne. 3. Kirjoittakaa ylös kunkin skenaarion kohdalle mikä vaikutus ongelmalla tulisi olla järjestelmään • Esimerkiksi "IP siirtyy masterilta slavelle, sovellus palauttaa alle 2 sekunnin ajan 500:ia ja toiminta palautuu"
  32. 32. Testaus Äänestäkää skenaarioista 5-7 mielenkiintoisinta testattavaksi ja aloittakaa testaus helpoimmasta Kunkin testin kohdalla kirjatkaa ylös mitä tapahtui "IP siirtyi masterilta slavelle, mutta slave ei hyväksynyt kirjoituksia. Sovellus ei myöskään palauttanut kahvoja ja jumiutui vapaiden kantakahvojen puutteeseen" Älkää jääkö tässä kohtaa pohtimaan miksei oletukset toteutuneet
  33. 33. Tulokset Testauksen tulokset on järkevää käydä läpi välittömästi. Mahdolliset parannusehdotukset ja -ideat kannattaa myös samassa tilaisuudessa kirjata projektin tikettijärjestelmään. Tilaisuuden jälkeen on hyvä kirjata yhteenveto tapahtuneesta ja jakaa se vähintään osallistujille. Bonuspisteitä esim. blogikirjoituksen tjsp tekemisestä
  34. 34. tl;dr Perinteisen ohjelmistokehityksen tasoiseen kehitykseen infrapuolella ei ole mitään estettä. Työkalut ja metodit ovat lähes identtiset. Käyttäjän kannalta on merkityksetöntä onko palvelu saavuttamattomissa javabugin vaiko palvelinongelman vuoksi
  35. 35. Kysyttävää? ps. http://www.shopify.com/careers

×