FlossCoach

Fonte: Wikiversidade
Saltar para a navegação Saltar para a pesquisa

João Guilherme - 130011126

Victor Henrique - 13/0145700

Introdução[editar | editar código-fonte]

Finalidade[editar | editar código-fonte]

O presente documento tem como objetivo definir um plano de gerenciamento para a configuração de software em um projeto escolhido, no caso, o FlossCoach.

Escopo[editar | editar código-fonte]

O plano de GCS tem como escopo a definição de técnicas e ferramentas a serem aplicadas ao FlossCoach a fim da sua melhora em relação a conceitos de Gerência de configuração de software.

Visão Geral[editar | editar código-fonte]

O documento está dividido da seguinte forma:

Projeto Escolhido - Breve descrição sobre o projeto escolhido pela dupla.

Ferramentas e técnicas a serem aplicadas - Definição e descrição de quais conceitos, ferramentas e técnicas foram esolhidas para serem aplicadas no projeto

Cronograma - Definição de datas para as atividades do projeto e marcos do mesmo.

Projeto Escolhido - Link Repositório[editar | editar código-fonte]

O projeto escolhido pela dupla foi o FlossCoach.

O FlossCoach pode ser definido como um portal de apoio a novatos com dificuldades em adentrar à comunidade de projetos de software livre.

Ferramentas e técnicas a serem aplicadas[editar | editar código-fonte]

Integração continua[editar | editar código-fonte]

“Integração Contínua é uma pratica de desenvolvimento de software onde os membros de um time integram seu trabalho frequentemente, geralmente cada pessoa integra pelo menos diariamente – podendo haver multiplas integrações por dia. Cada integração é verificada por um build automatizado (incluindo testes) para detectar erros de integração o mais rápido possível. Muitos times acham que essa abordagem leva a uma significante redução nos problemas de integração e permite que um time desenvolva software coeso mais rapidamente.” Martin Fowler

Deploy Automático[editar | editar código-fonte]

A fim de se evitar trabalho com o deploy do software a toda nova versão do mesmo, será implantado o deploy automático, juntamente com o Gitlab CI.

Ferramenta[editar | editar código-fonte]

GitLab CI - O Gitlab CI é o ambiente de Integração Contínua do GitLab.

Criação de ambiente de desenvolvimento portátil[editar | editar código-fonte]

Com a criação de uma box (box é o nome que o Vagrant utilizada para definir cada máquina virtual), qualquer novo desenvolvedor que queira ajudar no crescimento do projeto terá muita facilidade para começar a trabalhar com o FlossCoach

Ferramenta[editar | editar código-fonte]

Vagrant - Ferramenta para criação de máquinas virtuais.

Criação de testes funcionais[editar | editar código-fonte]

Como o Flosscoach é um projeto ainda no início de seu desenvolvimento, o mesmo não conta com uma suíte de testes funcionais, logo será criado os testes para as funcionalidades já existentes no projeto, contribuindo assim para uma melhor qualidade do software.

Ferramenta[editar | editar código-fonte]

Cucumber/Selenium - Através do cucumber são criados os testes, e o selenium é responsável por realizar a simulação em um navegador web.

Cronograma[editar | editar código-fonte]

Período Atividade
26/09 a 02/10 Definição do plano de projeto
03/10 a 09/10 Estudos sobre integração continua e deploy automático com o GitLab CI
10/10 a 17/10 Estruturação e implantação das técnicas de deploy automático e integração continua
18/10 a 26/10 Implementação dos testes funcionais
27/10 a 02/11 Estudo e criação da box com o vagrant
03/11 a 06/11 Conclusão, análise e revisão dos resultados
07/11 a 13/11 Criação da apresentação final e abertura do Merge-Request para o repositório oficial

Resultados[editar | editar código-fonte]

Integração Contínua[editar | editar código-fonte]

A integração continua foi feita com o GitLab CI e sua aplicação foi rápida e fácil. O processo necessário para aplicar a integração continua com essa ferramenta foi somente criar um arquivo .yml(o que pode ser feito na própria página do GitLab) contendo as configurações desejadas e salvá-lo. Após feito o commit, se tudo estiver correto, a integração contínua já estará implementada.

O arquivo  .gitlab-ci.yml ficou configurado da seguinte forma:

1 before_script:
2   - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
3   - ruby -v
4   - which ruby
5   - gem install bundler --no-ri --no-rdoc
6   - bundle install --jobs $(nproc)  "${FLAGS[@]}"
7 rspec:
8   script:
9     - bundle exec rspec

Deploy Automático[editar | editar código-fonte]

O deploy automático foi feito utilizando o Heroku para a hospedagem do FlossCoach e o GitLabCi para a automatização do deploy.

Para isso, seria somente necessário a adição de linhas indicando o deploy no arquivo .gitlab-ci.yml. Porém, foram necessárias várias modificações nas configurações do FlossCoach para prepará-lo pro ambiente de produção.

Os problemas encontrados, suas soluções e o resultado final se encontram a seguir.

Heroku x SQLite3[editar | editar código-fonte]

O heroku não consegue trabalhar com o SQLite3, com isso foi necessário adicionar gems diferentes para o banco em produção, utilizando o postgresql. O gemfile ficou da seguinte forma:

group :production do
  gem 'pg'
  gem 'uglifier'
end

group :development do
  gem 'sqlite3'
end

Necessidade de adicionar Gemfile.lock ao resposítório.[editar | editar código-fonte]

É necessário adicionar o Gemfile.lock para o repositório, para assegurar que as versões da gem do deploy são as mesma versões das gems encontradas na versão local da aplicação.

Arquivo do projeto com classe duplicada[editar | editar código-fonte]

Existia uma model no projeto, com uma classe (project), duplicada. Esse problema não se mostrava na aplicação em desenvolvimento por que o próprio rails suprimia esse erro. Já com o projeto em produção, o erro não era suprimido e não era possível subir o mesmo para o servidor. Após ser excluída a classe, foi possível subir o projeto.

Falta de preparação do projeto para ambiente de produção.[editar | editar código-fonte]

Todas essas gems e dependecias forma necessárias serem adicionadas no projeto, para que o mesmo ficasse apto ao ambiente de produção:

  • Gems
    • Uglifier
    • Production (Separação do banco para desenvolvimento e produção)
  • Resolv.conf (Dependencia necessária adicionada ao application.rb)
  • Secret Key (Não existia, somente foi adicionada uma referencia a key para produção)

Resultado Final[editar | editar código-fonte]

 1 staging:
 2   type: deploy
 3   script:
 4   - gem install dpl
 5   - dpl --provider=heroku --app=deploygcs --api-key=df17f508-fe8c-4e83-8bb5-c68763b573db
 6   only:
 7   - master
 8   
 9 production:
10   type: deploy
11   script:
12   - gem install dpl
13   - dpl --provider=heroku --api-key=$df17f508-fe8c-4e83-8bb5-c68763b573db
14   only:
15   - tags


Link para conferencia do deploy automático : https://deploygcs.herokuapp.com/


Criação de ambiente de desenvolvimento portátil[editar | editar código-fonte]

O ambiente de desenvolvimento foi feito no Vagrant.

Para isso deve ser criado o VagrantFile, no qual se encontram todas as dependencias necessárias para rodar o sistema.

O VagrantFile e os scripts usados foram os se seguintes :

VagrantFile:

 1 # -*- mode: ruby -*-
 2 # vi: set ft=ruby :
 3 
 4 Vagrant.configure("2") do |config|
 5 
 6   config.vm.box = "ubuntu/xenial64"
 7  
 8   config.vm.network "forwarded_port", guest: 3000, host: 3000
 9 
10   config.vm.provider "virtualbox" do |vb|
11     # Display the VirtualBox GUI when booting the machine
12     # vb.gui = true
13     # Customize the amount of memory on the VM:
14     vb.memory = "1024"
15   end
16 
17   # SHELL
18   config.vm.provision :shell, path: "install_rvm.sh", args: "stable", privileged: false
19   config.vm.provision :shell, path: "install_ruby.sh", args: "2.3.1", privileged: false
20   config.vm.provision :shell, path: "install_ruby.sh", args: "2.3.1 rails haml", privileged: false
21   config.vm.provision :shell, path: "provision.sh", args: "2.3.1 rails haml", privileged: false
22 end

install_rvm.sh:

1 gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
2 curl -sSL https://get.rvm.io | bash -s $1

install_ruby.sh:

1 #!/usr/bin/env bash
2 source $HOME/.rvm/scripts/rvm
3 rvm use --default --install $1
4 shift
5 if (( $# ))
6 then gem install $@
7 fi
8 rvm cleanup all

provision.sh:

 1 #!/usr/bin/env bash
 2 sudo apt-get update
 3 sudo apt-get install -y nodejs nodejs-legacy postgresql-common postgresql-9.5
 4 sudo apt-get install -y git curl automake build-essential bison
 5 sudo apt-get install -y libpq-dev libssl-dev libtool libcurl4-openssl-dev
 6 sudo apt-get install -y libyaml-dev libreadline-dev libxml2-dev libxslt1-dev
 7 sudo apt-get install -y libffi-dev libffi-dev libgdbm-dev libncurses5-dev
 8 sudo apt-get install -y libsqlite3-dev sqlite3 zlib1g-dev
 9 sudo apt-get install -y python-software-properties
10 rvm default ruby-2.3.1
11 gem install bundler
12 gem install nokogiri -v '1.6.8'
13 gem install rails
14 sudo apt-get autoremove
15 sudo apt-get autoclean
16 sudo apt-get update
17 cd /vagrant/
18 bundle install

Para executar o ambiente virtual, devem ser executados os seguintes comandos, em sequência:

  • vagrant up
  • vagrant provision
  • vagrant ssh

Criação de testes funcionais[editar | editar código-fonte]

Para criação/execução dos testes foram usadas as ferramentas selenium/cucumber, onde podemos ter uma simulação do uso da aplicação em um navegador web de maneira automatizada.

Como o software a ser analisado, já possui muitas funcionalidades, e no contexto do projeto, demandaria muito tempo para testar toda a aplicação, foram selecionadas apenas três para realização dos testes, que são:

  • F01- Editar perfil do usuário;
  • F02- Pesquisar projeto;
  • F03- Efetuar login/logout;

Para cada funcionalidade descrita anteriormente, são especificados alguns cenários, os quais contemplam 100% da funcionalidade. Ou seja, a funcionalidade só é considerada 100% testada, caso todos os cenários estejam testados.Esse cenários são descritos em linguagem natural através de steps que simulam o uso da aplicação. Abaixo encontra-se a descrição dos cenários referentes a cada feature:

edit_profile.feature:

 1 Feature: Edit profile user
 2 
 3   Scenario: Editing user profile filling all fields correctly
 4     Given I am logged into the application
 5     And is on the profile editing page
 6     And fill in all fields correctly
 7     When I click in button "Submit"
 8     Then I should see the message "User was successfully updated."
 9 
10   Scenario: Editing user profile by filling in all fields except the name field
11     Given I am logged into the application
12     And is on the profile editing page
13     And fill in all fields correctly  except the name field
14     When I click in button "Submit"
15     Then I should see the message "Name can't be blank"
16 
17 
18   Scenario: Editing user profile by filling in all fields except the email field
19     Given I am logged into the application
20     And is on the profile editing page
21     And fill in all fields correctly  except the email field
22     When I click in button "Submit"
23     Then I should see the message "Email can't be blank"
24 
25   Scenario: Editing user profile by filling in all fields except the password field
26     Given I am logged into the application
27     And is on the profile editing page
28     And fill in all fields correctly  except the password field
29     When I click in button "Submit"
30     Then I should see the message "Password can't be blank"
31 
32   Scenario: Editing user profile by filling in all fields except the password confirmation field
33     Given I am logged into the application
34     And is on the profile editing page
35     And fill in all fields correctly  except the password confirmation field
36     When I click in button "Submit"
37     Then I should see the message "Password confirmation doesn't match Password"

login.feature:

 1 Feature: login in the application
 2 
 3   Scenario: login with valid user
 4     Given I am in the homepage
 5     And fill in all login_fields correctly
 6     When I click in button "submit"
 7     Then I should see the message "Explore Flosscoach"
 8 
 9   Scenario: login with invalid user
10     Given I am in the homepage
11     And fill in all login_fields incorrectly
12     When I click in button "submit"
13     Then I should see the message "Invalid e-mail or password."
14 
15   Scenario: Logout
16     Given I am logged into the application
17     When I press button Logout
18     Then I should see the message "Please, visit us! Check our prototype and give us your feedback"

search_project.feature:

 1 Feature: Search a project
 2 
 3   Scenario: Search an existing project
 4     Given I am logged into the application
 5     And fill a project field with a existing project
 6     When I press the enter button
 7     Then I should see a project name
 8 
 9   Scenario: Search as nonexistent project
10     Given I am logged into the application
11     And fill a project field with a nonexistent project
12     When I press the enter button
13     Then I should see the message "Explore Flosscoach"


Após criados, os cenários preenchemos os steps com instruções ruby, e temos o seguinte arquivo:

steps.rb:

 1 Before do
 2   @user = User.new(name: "Teste", email: "teste@gmail.com", password: "123123", email_confirmed: true)
 3   @user.save
 4 
 5   @project = Project.new(name: "project")
 6   @project.save
 7 end
 8 
 9 Given(/^I am logged into the application$/) do
10   visit '/'
11   fill_in "user_email" , :with => "teste@gmail.com"
12   fill_in "user_password", :with => "123123"
13   click_button "submit"
14 end
15 
16 Given(/^is on the profile editing page$/) do
17   visit '/users/1/edit'
18 end
19 
20 
21 Given(/^fill in all fields correctly$/) do
22   fill_in "user_name" , :with => "Teste2"
23   fill_in "user_email" , :with => "teste2@gmail.com"
24   fill_in "user_password", :with => "123123"
25   fill_in "user_password_confirmation", :with => "123123"
26 end
27 
28 Given(/^fill in all fields correctly  except the name field$/) do
29   fill_in "user_email" , :with => "teste@gmail.com"
30   fill_in "user_password", :with => "123123"
31   fill_in "user_password_confirmation", :with => "123123"
32 end
33 
34 Given(/^fill in all fields correctly  except the email field$/) do
35   fill_in "user_name" , :with => "Teste"
36   fill_in "user_password", :with => "123123"
37   fill_in "user_password_confirmation", :with => "123123"
38 end
39 
40 Given(/^fill in all fields correctly  except the password field$/) do
41   fill_in "user_name" , :with => "Teste"
42   fill_in "user_email" , :with => "teste@gmail.com"
43   fill_in "user_password_confirmation", :with => "123123"
44 end
45 
46 Given(/^fill in all fields correctly  except the password confirmation field$/) do
47   fill_in "user_name" , :with => "Teste"
48   fill_in "user_email" , :with => "teste@gmail.com"
49   fill_in "user_password", :with => "123123"
50 end
51 
52 Given(/^I am in the homepage$/) do
53   visit '/'
54 end
55 
56 Given(/^fill in all login_fields correctly$/) do
57   fill_in "user_email" , :with => "teste@gmail.com"
58   fill_in "user_password", :with => "123123"
59 end
60 
61 
62 When(/^I click in button "([^"]*)"$/) do |arg1|
63   click_button arg1
64 end
65 
66 Then(/^I should see the message "([^"]*)"$/) do |arg1|
67   expect(page).to have_content(arg1)
68 end
69 
70 Given(/^fill in all login_fields incorrectly$/) do
71   fill_in "user_email" , :with => "teste@gmail.com"
72   fill_in "user_password", :with => "123456"
73 end
74 
75 When(/^I press button Logout$/) do
76   visit '/users/logout'
77 end
78 
79 Given(/^fill a project field with a existing project$/) do
80   fill_in "search", :with => "project"
81 end
82 
83 Then(/^I should see a project name$/) do
84   expect(page).to have_content("project")
85 end
86 
87 When(/^I press the enter button$/) do
88   find(:id, 'inputSearch').native.send_keys(:enter)
89 end
90 
91 Given(/^fill a project field with a nonexistent project$/) do
92   fill_in "search", :with => "nonexistent ---project"
93 end

Criados os steps, basta apena rodar o comando "cucumber" e os testes serão executados.