Recent Posts

Como configurar multiplos usuários SSH para o mesmo host

In .ssh folder, generate a new key:

$ ssh-keygen -t rsa -C "your-email-address" -f "id_rsa_OTHERUSER"
# Your identification has been saved in take_rsa.
Your public key has been saved in take_rsa.pub.
The key fingerprint is:
XXX
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
+-----------------+

Ensure ssh-agent is enabled:

$ eval "$(ssh-agent -s)"
# Agent pid 59566

Add your new key:

$ ssh-add ~/.ssh/id_rsa_OTHERUSER
# Identity added: id_rsa_OTHERUSER (id_rsa_OTHERUSER)

Edit your config file:

vim ~/.ssh/config

With this:

Host github-OTHERUSER
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_OTHERUSER

Your remote url should be:

git@github-OTHERUSER:company/myproject.git

You can update the user name and email in your repository

git config user.name "OTHER_USERNAME"
git config user.email "OTHER@EMAIL.COM"

Alguns comandos interessantes do git

Staching

Já passou pela situação de em determinado momento você está trabalhando em algo complexo e uma demanda urgente chega. Então você tem de parar o que está fazendo e trabalhar nesta demanda para só depois continuar o seu trabalho anterior?

A pergunta que surge é, o que fazer com o seu código? Commit pode não ser a solução uma vez que ele ainda não está finalizado.

Criar uma nova pasta para o projeto, executar o pull e trabalhar na nova demanda? Talvez sim, mas existe uma solução melhor!

Stashing existe justamente para isto, guarda seu código em um pilha para que posteriormente você possa recuperá-lo.

git stash

Neste ponto o código alterado é arquivado em uma pilha; Você pode trabalhar na demanda urgente.

Após finalizar a demanda utilize o comando apply para recuperar o seu código:

git stash apply

Este comando irá carregar novamente seus arquivos. É possível inclusive adicionar várias listas de stash.

git stash list

Para aplicar uma lista específica:

git stash apply stash@{2}

File Annotation

Quando nos deparamos com algum bug, já pensou em como recuperar quem inseriu aquele bug no código? Para descobrir teriamos de saber quem alterou determinada linha e quando.

Git tem um recurso chamado blame que permite listar quem e quando foi realizado a última alteração em determinada(s) linha(s).

git blame -L 2,6 myfile.txt
  • -L limita as linhas 2 a 6.
  • -C exibe alterações como no nome do arquivo

Submodules

Submodules são módulos do seu repositório, literalmente sub-repositórios dentro de um repositório master. Este recurso é muito útil por exemplo quando você tem um projeto de importação/projetos secundários ao projeto principal e deseja manter o código destes projetos em um repositório separado.

Sua utilização é bem simples:

git submodule add {git-url} {path}

Este comando irá criar um arquivo .gitmodules com o mapeamento de todos os seus sub-repositórios. A partir dai, você pode efetuar commits/pull/push normalmente o git irá tratar os sub-repositórios de forma separada ao repositório master.

Referencias

Get Starter with Boxstarter

First import modules in admin powershell

Import-Module Boxstarter.Chocolatey

Create a power shell script

Install-WindowsUpdate -acceptEula -getUpdatesFromMS
Set-WindowsExplorerOptions -EnableShowHiddenFilesFoldersDrives -EnableShowProtectedOSFiles -EnableShowFileExtensions -EnableShowFullPathInTitleBar
Set-TaskbarOptions -Size Small -Dock Bottom -Lock

Allow running PowerShell scripts

Update-ExecutionPolicy Unrestricted

Disable System Restore

disable-computerrestore -drive "C:\"

Disable hibernate

powershell -Command "Start-Process 'powercfg.exe' -Verb runAs -ArgumentList '/h off'"
if (Test-PendingReboot) { Invoke-Reboot }

Install chocolatey packages

choco install spotify
choco install dotnet3.5
choco install imdisk
if (Test-PendingReboot) { Invoke-Reboot }

Now yout can create a packge from script

New-PackageFromScript MyScript.ps1 "Dev-Boxstarter"

This will create a nuget package in local repository, see variable $Boxstarter.LocalRepo

Package with contents You can create package with contents to copy later. In this, I have in my-files folder, a .gitconfig file.

New-BoxstarterPackage -Name "Dev-Boxstarter" -Description "Sample box" -Path "C\my-files"

Later, in your script you can usage this command to copy files:

Copy-Item (Join-Path -Path (Get-PackageRoot($MyInvocation)) -ChildPath '.gitconfig') -Force $env:USERPROFILER\.gitconfig

Customize scripts After execute New-BoxstarterPackage, a nuget package will be create in $Boxstarter.LocalRepo folder. Lets open Dev-Boxstarter\tools\ChocolateyInstall.ps1.

Lets add first script created in this new file.

Generate package After finish configure scripts and files, we can make a nuget package:

Invoke-BoxstarterBuild "Dev-Boxstarter"
$files = Join-Path -Path $pwd.Path -ChildPath "content"
New-BoxstarterPackage -Name "Dev-Boxstarter" -Description "A box for .net developers" -path $files

Publish package

The first thing you mey now is that Boxstarte look for package in onrder: Local, Chocolatey feed, Boxstarter Community Feed (hosted in MyGet), the first package with same name finded, will be use.

You can define sources like this:

Set-BoxstarterConfig -LocalRepo "\\server\share\myRepo"

or

Set-BoxstarterConfig -NugetSources "http://www.myget.org/F/MyNugetFeed/api/v2;http://chocolatey.org/api/v2;http://www.myget.org/F/boxstarter/api/v2"

Myget for push package

We use a default community Boxstarter in MyGet to push our package. First we need a accesstoken to push our package:

After sign up, get you access token in your profile on MyGet.

nuget push SamplePackage.1.0.0.nupkg f1258b54-8143-4237-bc1a-89e14c3ab933 -Source https://www.myget.org/F/boxstarter/

Install package

Boxstarter use a ClickOnce installation, this mens you can simple navigate a URl e all is good!

START http://boxstarter.org/package/mwrock.DefaultInstall
ridermansb-devbox.boxstarte

$cred=Get-Credential
Install-BoxstarterPackage -PackageName "Dev-Boxstarter" -Credential $cred

Sample

I create a gist for my envairoments

Automatizando o fluxo do git

The Flow

Git é uma ótima ferramenta de source control, bem flexível permitindo que cada empresa/pessoa/projeto trabalhe de uma maneira diferente com um workflow específico. E como foi com os design patterns, quanto mais avançamos na utilização do git (ou qualquer outro source control) iremos nos deparar com alguns problemas e soluções. Estas soluções em alguns casos são bem parecidas e podem acabar virando um padrão/recomendação para utilização.

Com o git não foi diferente, podemos por exemplo trabalhar usando um Feature Branch Workflow ou Gitflow Workflow.

Neste artigo pretendo abordar o Gitflow Workflow que basicamente é uma extenssão do Feature Branch Workflow

Resumidamente o Gitflow Workflow consiste em:

  1. Branch master: Produção
  2. Branch releasexx: Preparação para a próxima versão
  3. Branch develop: Em Desenvolvimento
  4. Branch featurexxx: Em Desenvolvimento a feature x
  5. Branch hotfixxxx: Em Desenvolvimento o hotfix x
  6. Tag vX.X.X.X : Versão X

O processo consiste em desenvolver as features em branchs específicos, um para cada feature, e então realizar um merge com o branch develop, posteriormente com o branch release. Caso necessário necessário, hotfixes podem ser aplicados diretamente ao branch release para uma correção urgente.

gitflow

Isto é bastante comum, e faz todo sentido pois nos permite identificar e migrar de um ponto do código para outro “rapidamente” quando necessário, trabalhar com grandes equipes, além de manter uma rastreabilidade do código. Caso tenha interesse em aprofundar neste flow, todo este processo está descrito neste artigo, o objetivo aqui é demonstrar o gitflow e como ele pode nos ajudar a seguir fluxo de forma rápida e intuitiva.

O problema

O processo em sí não é o problema, e sim a quatidade de comandos que você tem de digitar ao passar por cada passo:

  1. Inicia uma feature: git checkout -b feature/xxx
  2. Work on feature …. git commit -a -m "My work"
  3. Finaliza uma feture: git checkout develop, git pull develop, git merge feature/xxx
  4. Hotfixes …
  5. Releases …

Sempre que aderimos a um processo, temos de pesar todos as vantagens e desvantagens, e procurar meios de automatizar para que não corramos o risco de não seguir ou utilizar de forma errada este processo.

Neste caso, precisamos automatizar a quantidade de código necessária para seguir este fluxo, além de tornar mais legível os passos necessários.

A solução

Gitflow é uma coleção de git extensions que permite abstrair este fluxo, tornado-o mais interativo e expressivo. Com ele podemos seguir este workflow de uma forma bem prática e intuitiva.

Instalação (Windows)

Apesar de muito bem descrito na página do produto, a instalação no Windows pode ser um pouco confuso, então resolvi compartilhar como fiz a instalação em minha máquina:

  1. Clone o repositório: git clone --recursive git://github.com/nvie/gitflow.git
  2. Navege para a pasta: cd gitflow\contrib\
  3. Execute o arquivo: msysgit-install.cmd Em modo admin

É importante que o Cygwin, msysgit, util-linux e o wget estejam devidamente instalados no seu pc;

Após realizar estes passos, no seu prompt de comando ao digitar git flow você deverá ver:

git flow
usage: git flow <subcommand>

Available subcommands are:
   init      Initialize a new git repo with support for the branching model.
   feature   Manage your feature branches.
   release   Manage your release branches.
   hotfix    Manage your hotfix branches.
   support   Manage your support branches.
   version   Shows version information.

Try 'git flow <subcommand> help' for details.

Get started

Agora que já instalamos gitflow, precisamos inicializá-lo usando o comando git flow init no seu repositório. Este comando irá configurar os branchs necessários para o workflow.

Feature Branches

Da mesma forma que no Feature Branch Workflow, o gitflow possui branches para cada feature.

git flow feature [list] # Lista as features
git flow feature start <name> # Inicia o branch para a feature específicada
git flow feature finish [<name|nameprefix>] # Finaliza o branch para a feature específicada
git flow feature publish <name> # Publica a feature no repositório central

Release Branches

Com a feature finalizada, podemos preparar a versão para produção. Release branches tem este objetivo. É nele por exemplo que você modifica versão nos arquivos, adiciona release notes, realiza testes.

git flow release start <version> # Inicia a versão
git flow release finish <version> # Finaliza a versão
git flow release publish <name> # Publica a versão no repositório central

Hotfixes Branches

Ao lançar uma versão eventuais bugs podem aparecer, esta branch é usada para correções de bugs em produção. Ao finalizar, o hotfix é aplicado ao branch master e develop.

git flow hotfix start <version>
git flow hotfix finish <version>
git flow hotfix publish <version>

Support Branches

Segundo a documentação são recursos esperimentais, onde o time desenvolve algo mas não quer aplicar a próxima release.

Usage

Sua utilização é bem simples, para trabalhar em uma nova feature use o comando git flow feature start <your feature>, ao finalizar esta feature git flow feature finish <your feature>.

O gitflow irá executar todos os comandos necessários para o workflow merge, branch, checkout etc.

Você pode publicar esta feature no repositório origin usando o comando: git flow feature publish <your feature> ou realizar um pull git flow feature pull <remote> <your feature>

Este mesmo conceito segue para release e hotfixes.

Projetos existentes

Se você deseja utilizar o gitflow em um projeto já em andamento, não existem problemas, somente algumas recumendações.

  1. Elimine todos os branches, exceto o master antes de iniciar o gitflow.
  2. Oriente a equipe a sempre usar git flow nos comandos git.

Após isso é só executar git flow init.

Conclusão

Eu realmente estou muito satisfeito com o gitflow, para se ter uma ideia de como ele automatiza este workflow para nós, um simples comando como: git flow release finish -F -p iteration01 é traduzido para:

git checkout master
git fetch origin master
git merge –no-ff iteration01
git tag -a iteration01
git push origin master
git checkout develop
git fetch origin develop
git merge –no-ff iteration01
git push origin develop
git branch –d iteration01

Imagine ter de digitar todos estes comandos sempre que finalizar uma release.

References

Meu prompt powershell

Você acha útil exibir todo o caminho no prompt? Pense bem, quando foi que esta informação te ajudou em algo? Quando navego pelo cmd, normalmente eu quero ir a algum lugar e não saber de onde vim! Afinal entende-se que eu seu de onde vim :).

Prompt original:

Prompt original com Posh-GIT

Com Posh-GIT

Eu nunca gostei do prompt, então fiz algumas pesquisas, inclusive no stackoverflow, e consegui chegar a algo que me agradou (obrigado @mmozuras).

Entendendo o PowerShell

O PowerShell possui um arquivo ps1 que é executado sempre que você abre uma nova janela. Este arquivo é o seu Profile e para descobrir sua localização é só você digitar $PROFILE no PowerShell que o path será exibido.

Configurando seu profile

Agora que já sabemos a localização do arquivo de profile, temos apenas de configurá-lo.

Abra o arquivo com um bloco de notas.

Caso você tenha instalado o Posh-GIT ou algum module, é bem provável que nas primeiras linhas esteja importando os modulos. Algo como: . '{Module-Path}\posh-git\profile.example.ps1'

Para configura nosso prompt temos apenas de criar uma function chamada prompt.

...

function prompt {
    $path = ""
    $pathbits = ([string]$pwd).split("\", [System.StringSplitOptions]::RemoveEmptyEntries)

    if($pathbits.length -eq 1) {
        $path = $pathbits[0] + "\"
    } else {
        $path = $pathbits[$pathbits.length - 1]
    }

    $host.UI.RawUi.WindowTitle = $path

    Write-Host($path) -nonewline -foregroundcolor Yellow

    $Global:GitStatus = Get-GitStatus
    Write-GitStatus $GitStatus

    Write-Host('>') -nonewline -foregroundcolor Yellow

    return " "
}

Enable-GitColors

Referências

Grunt - Getting Started 3-3

Este é o terceiro post da série sobre Grunt

Todo o código utilizado encontra-se no Github


Tarefas customizadas

Você pode criar sua própria task e definir sua lógica. Exemplo:

grunt.registerTask('custom', 'My custom task', function() {
  grunt.log.writeln('Seu código rodando aqui...');
});

A documentação do objeto grunt está disponível na documentação da API

Para rodar sua task, utilize a mesma nomenclatura de uma task normal: grunt custom.

Você pode inclusive passar targets para sua function:

grunt.registerTask('custom', 'My custom task', function(arg1, arg2) {
  grunt.log.writeln('Seu código rodando aqui...');
  if (arg1)
    grunt.log.writeln('Arg1: ' + arg1);
 if (arg2)
    grunt.log.writeln('Arg2: ' + arg2);
});

Para executar: grunt custom:Argumento1:Arqumento2

Function nada mais é do que um callback executado logo após a execução da task. Caso já tenha definido uma task (por exemplo coffee) nas configurações, então a task é executada e logo em seguida o callback:

grunt.registerTask('coffee', 'Log coffee compile.', function() {
  grunt.log.writeln('coffee:' + this.target + ' compiled!');
});

Desta forma, primeiro coffee será executado (compilado os arquivos JS) em seguida o callback.

Reutilizando código

A medida que o número de tasks cresce, a quantidade de códigos e a complexidade crescem juntos. E claro, consequentemente a manutenabilidade diminui.

Em Grunt existem alguns recursos que podem ajudar a manter o código mais limpo como Templates e Arquivos de configuração

Templates

Templates é a capacidade do GruntJS expandir configurações das tarefas. Por exemplo, muitas tasks como a Concat possui uma opção chamada banner que adiciona um texto no topo dos arquivos concatenados.

Vamos supor que em nossa empresa seja obrigatório adicionar no topo dos arquivos JS um texto e a data em que o arquivo foi gerado. Com Grunt poderíamos criar uma variável com este texto e utilizá-la em todas as nossas tasks:

concat: {
    options: {
        banner: '/* <%= copy %> \*/\n',
      },

...

copy: 'Desenvolvido por Riderman em <%= grunt.template.today("yyyy-mm-dd") %>'

Bem simples, tudo o que temos de fazer é colocar nossa variável entre <%= e %> e o Grunt fará o resto. O resultado é: /* Desenvolvido por Riderman em 2013-04-22 */

Podemos reutilizar esta variável por exemplo na task uglify.

Arquivos de configuração

Bem parecido com os templates com a única diferença que arquivos de configuração ficam em arquivos separados ao Gruntfile.js. Podendo ser JSON ou YAML.

Aqui na Bind Solution utilizamos bastante em nossa rotina de backups para armazenar paths e senhas por exemplo.

Sua utilização é a mesma que os templates, com um detalhe que você deve carrega-lo antes utilizando o comando: pkg: grunt.file.readJSON('meuarquivo.json')

A forma de utilização é a mesma: Olá <%= pkg.nome %>

Criação de plugins

Como todo bom framework, Grunt permite sua extensão através de plugins; O processo de criação é bem simples descrito na página do projeto.

Basta utilizar o template disponível no Github e criar seu código.

Grunt - Getting Started 2-3

Este é o segundo post da série sobre Grunt

Todo o código utilizado encontra-se no Github


Até o momento aprendemos o que é Grunt, sobre alguns plugins e como configurar tarefas simples. Neste post iremos aprofundar um pouco mais nas tasks para entender melhor sobre o porque das coisas. :)

Tasks

Configurações

Cada task é na verdade um comando a ser executado, e no Grunt podemos definir configurações para cada comando. Por exemplo, no post anterior quando definimos a task coffee temos uma configuração chamada compile:

...
coffee:{
    compile: {
        files: {
            "main.js": "main.coffee"
        }
    }
},
...

Quando rodamos o comando grunt coffee o resultado é este: Repare na configuração.

Compile coffee

Podemos inclusive definir mais do que uma configuração para algumas tasks (como mostrado abaixo), caso você não especifique nenhuma configuração o Grunt irá rodar todas.

...
coffee:{
    compile: {
        files: {
            "main.js": "main.coffee"
        }
    },
    compileJoin: {
        files: {
            "all.js": "\*.coffee"
        }
    }
},
...

E o resultado do comando grunt coffee:

Grant roda todas as tasks

Se desejar rodar uma task sobre uma configuração específica: grunt coffee:compileJoin.

Opções

Toda task no Grunt possui um atributo chamado options, que serve para definir algumas opções de configuração na execução da task. Por exemplo, no plugin grunt-contrib-coffee temos a opção bare nu que serve para gerar o .js nu (sem o invólucro de segurança de nível superior função.)

Exemplo:

...
coffee:{
    options: {
        bare: true
    },
    compile: {
        files: {
            "main.js": "main.coffee"
        }
    },
...

Desta forma, os arquivos .js gerados não terão uma função wrapper envolvendo todo o javascript. Isto se aplica a todas as configurações.

Options também se aplica às configurações:

...
coffee:{
    options: {
        bare: true
    },
    compile: {
        files: {
            "main.js": "main.coffee"
        }
    },
    compileJoin: {
        options: {
            bare: false
        },
        files: {
            "all.js": "\*.coffee"
        }
    }
},
...

Desta forma as opções definidas em compileJoin irão prevalecer, sobrescrevendo as opções do nível superior.

Files

É importante entender que Grunt foi feito para realizar operações em arquivos, por este motivo temos algumas abstrações como as propriedades src e dest. Por exemplo, nosso compileJoin pode ser escrito da seguinte forma:

...
    compileJoin: {
        options: {
            bare: false
        },
        src: "*.coffee"
        ,dest: "all.js"
    }
},
...

Ou:

files: [
    {src: ['main.coffee', 'js/*.coffee'], dest: 'all.js'},
    {src: ['src/aa1.coffee', 'src/aaa1.coffee'], dest: 'dest/a1.js'},
],

Existem também várias opções de filtros. Mas não entraremos em filtros neste momento.

Refatorando

Agora que entendemos como funcionam as tasks vamos fazer algo divertido :). No decorrer do desenvolvimento, temos pelo menos dois ambientes: O de dev e o de dist “distribuição” (aquela versão que vai para o ar).

É comum que no ambiente de dev tenhamos de executar uma série de tasks, e o mesmo acontece quando vamos publicar uma versão (dist).

Na versão de dev, como dito no post anterior , eu tenho de:

  • Compilar meus arquivos sass e coffee
  • Executar testes
  • Otimizar imagens
  • Compilar templates handlebars

e na versão de dist:

  • Minificar js e css
  • Concatenar
  • Lint
  • Compactar arquivos no formato zip
  • Enviar via FTP para o server

Não vamos fazer todas as tasks acima, mas só algumas pra termos uma noção de como Grunt pode ser útil.

Organizando a estrutura

Primeiramente vamos organizar nossa estrutura de arquivos.

Estrutura de pastas

Versão dev

Compilar meus arquivos coffee

Nosso objetivo é compilar nossos arquivos .coffee para a mesma pasta de origem (mantendo o nome do arquivo). Para isto vamos utilizar o recurso Building the files object dynamically, conforme configuração abaixo:

coffee: {
    dev: {
        expand: true
        ,cwd: "js/"
        ,src: ["**/*.coffee"]
        ,dest: "js/"
        ,ext: ".js"
    }
}

A propriedade expand indica que esta é uma configuração especial. Basicamente estamos dizendo ao Grunt que os arquivos da pasta js proriedade cwd que contém a extensão .coffee e em todos os sub-diretórios proriedade src serão compilados para a extensão .js proriedade ext na mesma pasta de origem proriedade dest.

Para este nosso exemplo não temos sub-diretórios na pasta js, porém serve como dica :).

Otimizar imagens

  1. Primeiramente instale o plugin grunt-contrib-imagemin para otimização de imagens.
  2. Adicione 3 imagens na pasta img.

Configuração

imagemin: {
    options: {
        optimizationLevel: 3
    },
    dev: {
        expand: true
        ,cwd: "img/"
        ,src: ["\*\*/\*.jpg"]
        ,dest: "img/"
        ,ext: ".jpg"
    }
}

Versão dist

Minificar js e concatenar

Os plugins para minificar (grunt-contrib-uglify) e concatenar (grunt-contrib-concat) já estão instalados em nosso projeto, tudo o que temos que fazer é modificar sua configuração para:

uglify: {
    dist: {
        files: {
            'dist/all.js': 'dist/all.js'
        }
    }
},
concat: {
    dist: {
        src: 'js/\*.js',
        dest: 'dist/all.js'
    }
},

Alias

Observe que primeiro devemos concatenar e só então minificar o arquivo js. Então vamos aprender sobre Alias e como executar várias tasks em uma determinada ordem.

Alias nada mais é do que uma lista de tarefas que devem ser executadas em uma determinada ordem. Por exemplo, ao executarmos grunt sem informar nenhuma task veja o que ocorre:

Default task grunt

Observe que grunt tenta rodar uma task default que não existe. Então podemos criar um Alias chamado default e listar as tasks que desejamos que rode caso nenhuma task seja definda:

grunt.registerTask('default', ['coffee:dev', 'imagemin:dev'])

Desta forma, as duas tasks serão executadas nesta ordem caso nenhuma outra seja informada:

Rodando task default caso nenhuma task seja definida

Seguindo esta linha, podemos criar um alias para rodar as tasks relacionadas a dist:

grunt.registerTask('dist', ['concat:dist', 'uglify:dist'])

e então rodar o grunt grunt dist

Rodando task dist (alias) no grunt

No próximo post vamos aprender como criar e customizar estas tasks :)

Todo o código utilizado encontra-se no Github

Referências:

Testes de interface com PageObjects e Selenium

Você ja ouviu falar sobre PageObjects ?

Neste artigo, pretendo apresentar o básico sobre PageObjects e como este pattern (sim ele e um pattern) pode nos ajudar com nossos testes de interface no selenium.

O problema

Sempre que criamos testes de interface, por mais oranizado que sejamos, com o passar do tempo teremos dificuldades para entender os testes e fazer adaptações/melhorias. Imagine uma tela com 20 campos, abas, integrações via REST, campos calculados etc.. como seria os testes para esta página?

Imagine isto por todo o código:

driver.FindElement(By.Name("userName")).SendKeys(UserName);
driver.FindElement(By.Name("password")).SendKeys(Password);
driver.FindElement(By.Name("login")).Click();

O problema deste tipo de codigo é a poluição, driver, FindElement, By.Name, SendKeys não diz nada para o nosso negócio!

O que é PageObjects

PageObjects é um pattern que define uma classe para cada página de nossa aplicação, desta forma podemos abstrair detalhes de implementação facilitando os testes. A ideia e simples, em uma página de Logon, temos os campos Login e Senha, neste caso teremos uma class LoginPage com as propriedades Login e Senha representando cada campo e um método chamado Logar representando a ação de logar. Assim teremos as funcionalidades da nossa pagina abstraidas em uma classe.

Exemplo prático

Vamos testar uma tela simples de logon, com dois inputs login e senha e um botão de login.

Specs

Temos de testar as 3 situações, usuário não digitou nenhum dado, usuário digitou dados incorretos ou usuário digitou dados corretos. Todas descritas na epsecificação abaixo:

Feature: Logon

Scenario Outline: Ao clicar em logon sem informar usuário e senha o sistema deve exibir uma mensagem
    Given Eu acessei o site com o navegador <browser>
    When Eu pressionar Logon
    Then Deve ser exibido a mensagem Campo usuário é obrigatório
    And Deve ser exibido a mensagem Campo senha é obrigatório

Scenario Outline: Ao clicar em logon com usuário e senha inválidos
    Given Eu acessei o site com o navegador <browser>
    And Eu inseri os dados de acesso UsuarioFake e SenhaFake
    When Eu pressionar Logon
    Then Deve ser exibido a mensagem usuário e/ou senha inválido(s)

Scenario Outline: Ao clicar em logon
    Given Eu acessei o site com o navegador <browser>
    And Eu inseri os dados de acesso UsuarioOk e SenhaOk
    When Eu pressionar Logon
    Then Deve redirecionar para a página inicial

Steps

Para exemplificar, optei por mostrar os steps primeiro para demonstrar como o código fica mais limpo e fácil de ler usando PageObjects:

Repare que a ação de clicar em um botão no site é um método em nossa classe, facilitando bastante a leitura e o entendimento dos nossos testes.

[Given(@"Eu acessei o site com o navegador (.*)")]
public void GivenEuAsseseiOSistemaComONavegador(string browser)
{
    CurrentBrowser = browser;
    CurrentPageObject = new LogonPage(WebBrowser.Current);
}

[Given(@"Eu inseri os dados de acesso (.*) e (.*)")]
public void GivenEuInseriOsDadosDeAcesso(string usuario, string senha)
{
    CurrentPageObject.Usuario = usuario;
    CurrentPageObject.Senha = senha;
}

[When(@"Eu pressionar Logon")]
public void WhenEuPressionarLogon()
{
    CurrentPageObject.Logon();
}

[Then(@"Deve ser exibido a mensagem (.*)")]
public void ThenDeveSerExibidoAMensagem(string mensagem)
{
    CurrentPageObject.Alerts.Any(p => p.Mensagem == mensagem).BeTrue();
}

[Then(@"Deve redirecionar para a página inicial")]
public void ThenDeveRedirecionarParaAPaginaInicial()
{
    return WebBrowser.Current.Title.Contains(PageTitle);
}

PageObjects

Aqui teremos nossa classe com todos os detalhes de implementação da página: Optei por exibir apenas o que é importante com o objetivo de melhorar a didática deste artigo.

public class LogonPage
{
    private IWebDriver driver;

    [FindsBy(How = How.Name, Using = "usuario")]
    private IWebElement usuarioElement;

    [FindsBy(How = How.Name, Using = "senha")]
    private IWebElement senhaElement;

    [FindsBy(How = How.Name, Using = "logon")]
    private IWebElement logorElement;

    public string Usuario { get { return usuarioElement.Text; } set { usuarioElement.SendKeys(value); } }
    public string Senha { get { return senhaElement.Text; } set { senhaElement.SendKeys(value); } }

    public LogonPage(IWebDriver drive)
    {
        PageFactory.InitElements(driver, this);
    }

    public void Logon()
    {
        logorElement.click()
    }
}

Conclusão

Programar é a arte de simplificar as coisas, não é o que você consegue fazer com uma tecnologia foda, é como você usa esta tecnologia para simplificar ainda mais o seu código. PageObjects tem um poder incrível, com este pattern podemos melhorar e muito a manutenabilidade de nossos testes. Isto nos deixa mais animados a escrever ainda mais testes e consequentimente melhorando a cobertura de testes em nosso código. Pense por exemplo em quando você tem de adicionar um novo campo no html, e esta alteração quebra nossos testes. Com PageObjects, resolver estes tipos de problemas fica bem mais simples e pontual.

Reference

Convertendo repositórios mercurial (HG) para git (no windows)

Para exportar repositórios Mercurial para Git vamos precisar de uma ferramenta chamada fast-export;  

A melhor forma de obter, é clonar o repositório:

git clone git://repo.or.cz/fast-export.git

Inicialize um repositório git

git init src.git

Use o fast-export para exportar o projeto

cd src.git
hg-fast-export.sh -r

Windows

Ao tentar realizar esta tarefa no Windows tive alguns problemas (listados abaixo), uma forma de contornar é criar uma VM (cloud ou local usando o VirtualBox).

VM

  • Crie uma VM e contecte-se nela.
  • Instale o git e o mercurial (sudo apt-get install git mercurial)
  • Clone o repositório hg-fast-export git clone https://github.com/frej/fast-export.git

Com a VM configurada:

  • Clone o repositório mercurial que deseja converter hg clone https://your/hg/repo/address/your-repo-hg
  • Crie uma pasta para o repositório git mkdir your-repo-git
  • Entre nesta pasta cd your-repo-git
  • Inicialize o git git init
  • Converta ../fast-export/hg-fast-export.sh -r ../your-repo-hg/

Publicando novo repositório GIT

  • Adicione origin para o novo repositório git remote add origin https://your/git/repo/address
  • Push todos os branches e tags git push -u origin --all

E por último, lembre-se de mirar seu .hgignore para o equivalente .gitignore

Principais problemas

Ao executar hg-fast-export.sh

Branch name doesn’t conform to GIT standards: refs/heads/master’  

Para corrigir, edite o arquivo hg-fast-export.py.

    if sys.platform == “win32”:         import os, msvcrt         msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)


‘ImportError: No module named mercurial’

Significa que o Python não reconhece o Mercurial. Para corrigir, instale o Mercurial.

easy_install -U mercurial

Ao instalar mercurial

Setup script exited with error: Unable to find vcvarsall.bat

Para corrigir, crie um arquivo distutils.cfg em %PYTHONHOME%\Lib\distutils com o seguinte conteúdo:

    [build]     compiler=mingw32

Instruções neste link.

Fonte

App-get para Windows? Conheca o Chocolatey!

Chocolatey é uma especie de App-get para Windows.

Conceito

Para quem não sabe, app-get é um app do Linux que permite que você possa instalar, remover e atualizar aplicativos de forma fácil (por linha de comando) no Linux.

Algo como: apt-get install dropbox irá baixar o dropbox e instala-lo em sua máquina. Ou: app-get upgrade irá atualizar todos os apps em sua máquina.

Mais detalhes sobre o app-get neste link

Problema

Diferente do Linux, no Windows não temos um app nativo como este, e para instalar algum aplicativo temos de:

  1. Entrar no site do fabricante
  2. Baixar o instalador (.exe ou .msi)
  3. Executar o instalador

O processo complica ainda mais quando queremos atualizar alguma app. Temos de entrar em cada app, procurar pelo comando de atualizar “Check for updates” e atualizar.

Quando pensamos em dezenas (talvez centenas) de apps isso se torna um grande problema instalar e manter todas estas apps.

Solução

Chocolatey é como um app-get para Windows, permite que você instale, atualize e remova apps via linha de comando.

Algo como: cinst dropbox para instalar o Dropbox. Ou: cup all para atualizar todas as apps instaladas.

E sim, é open-source!

Por onde começar?

Primeiro instale o Chocolatey! :). Não vou entrar em detalhes sobre a instalação, como ele funciona como um pacote nuget, a instalação é como em qualquer pacote que já tenha instalado.

Para simplificar recomendo copiar e colar o código de instalação disponível na página principal do projeto ou neste link via PowerShell ou CMD.

Comandos

Após feito a instalação, uma lista de comandos estará disponível no prompt do Windows.

Buscar

chocolatey list packageName ou clist packageName lista as apps disponíveis para instalação. Você pode filtrar, listar versões betas etc.

Exemplo: clist dropbox para buscar apps com o nome dropbox

wiki do comando.

Instalar

chocolatey install packageName ou cinst packageName baixa e instala o app em sua máquina.

Algo bacana no Chocolatey é que você pode criar um arquivo como Packages.config contendo todas as apps que deseja instalar.

<?xml version="1.0" encoding="utf-8"?>
	<packages>
	  <package id="apackage" />
	  <package id="anotherPackage" version="1.1" />
	  <package id="chocolateytestpackage" version="0.1" source="somelocation" />
	</packages>

Desta forma, com um único comando cinst packages.config todas as apps neste XML serão baixadas e instaladas em sua máquina.

Apps são pacotes nugets hospedados no servidor do Chocolatey. Se deseja hospedar essas apps em seu PC local ou mesmo em um servidor próprio. O elemento source (contendo um diretório local, na rede ou mesmo uma URL) defini qual a fonte desta app.

wiki do comando.

Remover

chocolatey uninstall packageName ou cuninst packageName

Este é bem complexo, vou deixar para outro post. :)

wiki do comando

Atualizar

chocolatey update packageName ou cup packageName Sabe aquele problema de ter de ir ao site do fabricante, verificar se existe uma versão mais nova, comparar com a versão instalada em sua máquina. Pois é, não existe mais.

cup dropbox Verifica se existe uma nova versão, se sim baixa e instala automaticamente.
cup all Verifica se existe novas versões em todas as apps instaladas.
chocolatey update Atualiza o Chocolatey para a última versão.

wiki do comando

Versão

chocolatey version packageName ou cver packageName

Este comando simplesmente compara a versão instalada com a versão disponível no feed.

cver dropbox vai retornar a versão instalada e a versão disponível no feed.

wiki do comando

WebPI

WebPI ou Web Plataform Installer é basicamente um app da Microsoft onde você pode baixar e configurar componentes no Windows.

Então vamos instalar por exemplo o IISExpress: chocolatey webpi IISExpress ou cwebpi IISExpress irá baixar (via WebPI) e instalar o IIS Express localmente.

Se desejar ainda pode utilizar o comando clist, basta definir o source: cinst IISExpress -source webpi

wiki do comando

ATENÇÃO Para que este comando funcione, você deve instalar a versão Command Line do WebPI cinst webpicommandline.

Mais comandos

Chocolatey tem vários outros comandos interessantes como cwindowsfeatures featureName para instalar algum recurso do Windows, ou cpython packageName para quem brinca com Phyton e cgem packageName para quem brinca com Ruby Gems.

Para mais informações sobre os comandos disponíveis acesse este link.

Tips

Listando as apps instaladas Uma dificuldade que tive foi em listar todas as apps instaladas em minha máquina. Depois de uma rápida pesquisa encontrei este link.

cver all -localonly para listar todas as apps instaladas.

Grunt - Getting Started 1-3

Este é o primeiro post de uma series com 3 post sobre Grunt.

Todo o código utilizado encontra-se no Github


Em uma simples frase, Grunt é um automatizador de tarefas! Seu objetivo é automatizar tarefas repetitivas, por exemplo: Compactar arquivos, concatenar, minificar, executar testes e centenas de outras tarefas, tudo isso de uma forma altamente flexível!

Problema

São diversos problemas que esta ferramenta se propõe a solucionar, tudo depende do que você está precisando.

Eu (como desenvolvedor web) tenho de: * Compilar meus arquivos sass e coffee * Executar testes * Otimizar imagens * Compilar templates handlebars

Para publicar um website: * Minificar js e css * Concatenar * Lint * Compactar arquivos no formato zip * Enviar via FTP para o server

Percebe como são repetitivas estas tarefas? Com Grunt o podemos automatizar tudo isso.

Primeiros passos

Grunt roda como um modulo Nodejs, sua instalação é bem simples: npm install -g grunt-cli, na página Getting started você encontra mais detalhes sobre a instalação.

Não vou entrar em detalhes sobre o que é Nodejs ou como instalá-lo (sugiro instalação via Chocolatey cinst nodejs.install) pois não é o objetivo deste post.

Preparando o ambiente

Tipicamente Grunt requer dois arquivos package.json responsável por descrever o projeto e Gruntfile.js onde você irá definir suas tasks e carregar os plugins.

package.json

{
  "author": "Riderman de Sousa Barbosa",
  "name": "grunt-started",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.0"
  }
}

A propriedade mais importante é a devDependencies que contém todas as dependências do seu projeto. Repare que nossa primeira dependência é o próprio Grunt. Isto porque grunt-cli serve apenas para rodar a versão ao lado do Gruntfile.js.

> Til ~ indica que deve ser maior ou igual a versão indicada e menor do que a próxima grande versão. Mais detalhes neste link

Instalando o Grunt em nosso projeto

O próximo passo é pedir ao npm para instalar todas as dependências descritas em nosso package.json (em nosso caso apenas o grunt);

npm install

Primeira task (coffee)

Apenas o grunt não nos ajuda em nada, para fazer algo mais real precisamos de plugins. Por exemplo, se quisermos compilar nossos arquivos .coffee para .js precisamos de um plugin para realizar esta tarefa.

Existem diversos plugins disponíveis, desde cópia de arquivos até mesmo enviar arquivos por FTP. O time do Grunt mantém o grunt-contrib, uma coleção de 26 plugins (até a data de publicação deste post), cada um responsável por uma tarefa. Além destes, na página do projeto você pode encontrar dezenas (ou centenas) de outros plugins. E se não achar o que deseja, você pode inclusive criar sua própria task (mais detalhes no último post da série).

Para esta primeira task vamos compilar nossos arquivos .coffee para .js.

Instalando o plugin

Primeiramente precisamos instalar o plugin:

npm install grunt-contrib-coffee --save-dev

--save-dev adiciona este plugin como dependência no nosso arquivo package.json. Após executado o arquivo terá uma linha extra:

"devDependencies": {
  "grunt": "~0.4.0",
  "grunt-contrib": "~0.6.1"  &lt;-- Linha extra
}

Configurando Como dito anteriormente, grunt requer dois arquivos package.json e o Gruntfile.js. Então crie um novo arquivo com o nome Gruntfile.js e o seguinte conteúdo:

module.exports = function(grunt) {
  // Configurações
  grunt.initConfig({
    coffee:{
        compile: {
            files: {
                "main.js": "main.coffee"
            }
        }
    }
  });

  // Plugins
  grunt.loadNpmTasks('grunt-contrib-coffee');
};

O arquivo nada mais é do que uma configuração das tasks. Como configurar depende de cada plugin, neste caso a documentação deste plugin encontra-se neste link

main.js

Como ainda não temos o arquivo, vamos criá-lo:

calc = (a, b) -&gt; a + b
result = calc 1, 2
console.log result

Simples, e não faz nada útil. Mas para teste é suficiente! :)

Testando

grunt coffee

E um novo arquivo main.js é criado.

Segunda task (watch)

Para esta segunda task, vamos vigiar este arquivo, caso sofra alteração grunt deverá compilar novamente para .js. Para realizar esta tarefa precisaremos do plugin grunt-contrib-watch.

npm install grunt-contrib-watch --save-dev

Novamente uma nova linha é adicionada em nosso package.json:

...
  "devDependencies": {
    ...
    "grunt-contrib-watch": "~0.3.1" &lt;-- Linha adicionada
    .

..

Da mesma forma, precisaremos carregar a task para o nodejs. Altere o arquivo Gruntfile.js:

module.exports = function(grunt) {
  // Configurações
  grunt.initConfig({
    coffee:{
        compile: {
            files: {
                "main.js": "main.coffee"
            }
        }
    },
    watch: { // &lt;---- Nova configuração ----
        files: 'main.coffee',
        tasks: ['coffee']
    }

  });

  // Plugins
  grunt.loadNpmTasks('grunt-contrib-coffee');
  grunt.loadNpmTasks('grunt-contrib-watch'); // &lt;-- Carrega a task para o NodeJS ----
};

Agora é só utilizar:

grunt watch

Tente realizar uma modificação qualquer no arquivo main.coffee e veja o que acontece.

Tasks uglify e concat

Agora que já estamos bons, vamos adicionar mais dois plugins, instale o grunt-contrib-uglify e o grunt-contrib-concat. Baixe também o jquery e adicione-o ao nosso projeto.

Após feita a instalação, modifique seu Gruntfile.js

uglify: {
    my_target: {
      files: {
        'main.min.js': ['main.js']
      }
    }
  }
concat: {
        basic: {
            src: ['jquery-1.9.1.js', 'main.js'],
            dest: 'all.js'
        }
    }
    ...
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');

Então é só rodar: grunt uglify ou grunt concat.

Por enquanto é só, se desejar todo o código utilizado neste post encontra-se neste link. No próximo post da série veremos como executar várias tasks de uma vez, executar tasks seguindo uma configuração etc.. Ficará bem mais interessante e faremos algo útil :).

Referências

  1. Grow Up With Grunt by Ben Alman
  2. Build Podcast 021 Gruntjs
  3. Grunt - The Basics
  4. Frequently Asked Questions
  5. GruntJs ‘grunt’ cmd opens Visual Studio?
  6. A Tutorial for Getting Started with Grunt[](null)

Múltiplas instâncias do Dropbox, Google Drive, Google Talk no seu PC

Hoje vou mostrar como executar duas (ou mais) contas do Dropbox, Google Talks e Google Drive.

O principal motivo de não conseguirmos rodar duas instâncias do Dropbox por exemplo é pelo fato de que ao executar a aplicação ela será executada com o contexto do usuário logado. Sabendo disto, tudo o que temos de fazer é executar a app em um contexto de outro usuário.

Em outros casos, como o Google Talk, a opção simplesmente está desabilitada por padrão. Tudo o que temos de fazer é habilita-la.

Criando o ambiente

Primeiramente precisaremos de um outro contexto (usuário) para executar a aplicação. Então crie um novo usuário com senha no seu Windows. Não precisa ter privilégios administrativos!

Para referência futuras, chamaremos este usuário de Usuário secundário.

Tipo de conta para rodar múltiplas contas

Dropbox e Google Drive

Instalação

Efetue o login com o usuário secundário, baixe e instale o Dropbox e o Google Drive

Lembre-se de selecionar um local acessível aos dois usuários, para isto utilize as configurações avançadas para definir onde a app irá sincronizar os arquivos.

Configurações avançadas para selecionar a pasta de sincronização

Recomendo selecionar uma pasta em uma outra partição do HD.

Rodar a app em um contexto de outro usuário

A grande jogada é executar as apps no usuário principal porém com o contexto do nosso usuário secundário. Para isto vamos utilizar um comando do Windows chamado runas.

Exemplo: runas /user:USERNAME /savecred c:/users/usuario-secundario/path/to/dropbox/google-drive.exe

Este comando permite que rodemos aplicações como se fossemos outro usuário.

Como localizar a pasta de instalação?

Acesse o Task Manager (Ctrl + R, digite taskmgr) localize o processo Dropbox (32 bit) e Google Drive (32 bit) e com o botão direito escolha Open File Location.

File location do Dropbox

Atalho

Retorne ao usuário principal e navegue até o diretório de instalação (que buscamos no passo anterior) e crie um atalho no Desktop.

Atalho para o Dropbox

Agora temos de configurá-lo para executar as apps contexto do usuário secundário. Com o botão direito, modifique a propriedade Target do atalho para:

runas /user:"{Usuario Secundario Aqui}" /savecred "c:/path/to/file.exe"

Isto fará com que a app seja excutada em um outro contexto.

Repita estes passos para o Dropbox e Google Drive.

Google Talk

O Google Talk é mais simples! Por padrão a aplicação não permite múltiplas instâncias, para habilitar esta opção temos de adicionar o parâmetro /nomutex no path de execução da app. Modifique o atalho do seu Google Talk para:

Modificando o atalho do Google Talk para aceitar múltiplas instâncias

Agora sempre que você executar o Google Talk, outra instância da app será aberta, permitindo logon com vários usuários.

Referências

  1. MULTIPLE DROPBOX INSTANCES ON WINDOWS
  2. How to Run Multiple Instances of Dropbox in Windows 7
  3. How to Use Multiple Dropbox Accounts on One Computer
  4. Running Multiple Instances of Google Talk (GTalk Polygamy) and Login as Multi Users
  5. Switch between multiple Google Drive accounts

Doskey para criar alias de comandos no Windows

Eu confesso, sou fã do MacOS e do Ubuntu. Em termos de designer os dois deixaram o Windows XP/Vista/7/8 e acredito que até o 9 (quando sair rs) bem para trás. Em termos de recursos e usabilidade eu não sei, nunca trabalhei efetivamente com nenhum dos dois. Meus conhecimentos se limitam à VMs de testes que instalei para conhecer os dois sistemas operacionais.

O pouco que conheço dos recursos, já sinto falta no Windows, por exemplo o apt-get do Linux. Uma ótima ferramenta para você instalar e atualizar aplicativos via linha de comando. Felizmente, existem soluções relativamente semelhantes para Windows (no caso do apt-get, o Chocolatey por exemplo.

Neste post vou mostrar como utilizar o doskey, uma ferramenta nativa do Windows para criar alias de comandos DOS (igualmente o comando alias no MacOS e Linux).

Problema

Em diversas ocasiões, quando trabalhamos via linha de comandos, temos de repetir diversos comandos várias e várias vezes. Exemplo, se quisermos exibir apenas os subdiretórios de uma pasta, ordenados pelo nome em uma visualização lado a lado.

dir /AD /ON /W

Dir para listar diretórios ordenados em ordem alfabética no DOS

Imagine se toda vez que desejarmos listar os diretórios desta forma, tivermos de digitar todo o comando novamente. Ficaria inviável.

No Mac existe um comando chamado alias, onde basicamente você cria um alias para executar um comando. Exemplo: alias documents='cd ~/Documents', sempre que digitar documents o comando cd ~/Documents será executado.

No Linux alias lls=ls -l, sempre que digitar lls o comando ls -l será executado.

No Windows ? doskey.

Neste post vou explicar como configurar o doskey para listar os diretórios em ordem alfabética e lado a lado com o comando dird.

Solução

Doskey realiza a mesma função que o alias do Linux/Mac, sua utilização é bem parecida dosley <alias>=<comando>. Então vamos criar nossa primeira alias: Com o DOS aberto digite:

doskey dird=dir /AD /ON /W e teste o comando dird

Funcionou! :)

Agora, feche e abra uma nova janela do DOS e tente executar o comando novamente. Um erro de 'dird' is not recognized as an internal or external command.... Isto ocorre porque o comando que criamos fica ativo apenas no ambiente atual do DOS. Se fecharmos o DOS, todos estes comandos se perdem.

Bom, não queremos parte da solução, e sim a solução completa.

Persistir um comando no DOS

Para que nossos comandos não se percam, precisamos persistir os comandos no ambiente do DOS. Para realizamos esta tarefa vamos precisar do regedit.

Basicamente, sempre que uma janela do DOS for aberta, um arquivo autorun.bat será executado automaticamente criando nossos alias.

  • Crie um novo arquivo chamado autorun.bat.
  • Adicione o comando para criar nossa alias: doskey dird=dir /AD /ON /W no arquivo autorun.bat e salve em uma pasta qualquer na sua máquina.
  • Abra o regedit e procure pela entrada HKEY_CURRENT_USER\Software\Microsoft\Command Processor
  • Adicione uma nova entrada com o nome AutoRun e o valor como o caminho completo para nosso arquivo autorun.bat.

Editando o regedit para persistir o doskey

Agora é só testar, feche o DOS e abra novamente. Repare que sempre que você abre uma nova janela do DOS, o autorun é executado. Persistindo assim os comandos do doskey.

Uma dica, é adicionar no início do autorun.bat o comando @echo off para evitar que sejam exibidos os comandos executados pelo autorun.bat. Não se esqueça de restaurar as configurações do echo para @echo on no final do arquivo.

@echo off
doskey dird=dir /AD /ON /W
@echo on

Opções de execução do doskey

Na página da ferramenta está documentado as opções disponíveis para o doskey como:

  • doskey /macros: Lista todas as macros configuradas
  • doskey /history: Histórico de comandos executados no DOS

Alias para Sublime Text 2

Minha real necessidade com este recurso não foi listar de forma amigável os diretórios :), e sim executar o Sublime Text 2 já com a pasta atual como projeto.

O doskey que utilizei foi: doskey subl="C:\Program Files\Sublime Text 2\sublime_text.exe" $*.

$* representa todos os parâmetros passados pela execução, exemplo: subl "c:\ab" parametro2

Referências:

Granvando CD-ISO via linha de comando

Em minha empresa, existem rotinas de backups automatizados, tanto da base de dados quanto dos arquivos gerados pelo cliente. Sempre que a soma dos backups chegam a 4G um arquivo ISO é criado.

Isto é feito para cada cliente, então vi a necessidade de automatizar esta tarefa e para minha sorte CD Burner XP possui acesso via linha de comando. Vamos entender como funciona.

Este tutorial entende que você o CDBurnerXP já está instalado em sua máquina

Ambiente

Path do Windows

Para facilitar o acesso vamos adicionar ao PATH do Windows o app command line do CD Burner XP

Em System > Advanced system settings > Advanced clique em Environment Variables...

Selecione Path e clique em Editar

Path Windows para CD Burner XP via command line

Ou %PROGRAMFILES%\CDBurnerXP\cdbxpcmd.exe

Erro conhecido até a versão 4.5.1.3868

Em minha primeira tentativa o erro abaixo foi exibido:

> Error HRESULT E_FAIL has been returned from a call to a COM component

Pesquisando na internet descobri este forum e lendo as postagens, aparentemente o erro ocorre quando não há nenhum drive na máquina. Para solucionar (temporariamente assim espero) o problema utilizei a ferramenta Virtual Clone Drive que simula um drive em meu PC.

Caso não tenha nenhum drive de CD ou DVD, instale a ferramenta e adicione um drive.

Granvando para ISO

Agora estamos prontos para gravar um CD via linha de comando apenas utilizando o comando cdbxpcmd em nosso console.

Grava todos os arquivos da pasta especificada em ISO e fecha o disco:

cdbxpcmd --burn-data -folder:"{Caminho da pasta}" -iso:"{Caminho onde irá salvar o ISO}.iso" -name:"{Nome do disco}" -close

Granvando em CD

Antes de gravar arquivos em um CD precisamos especificar qual driver iremos utilizar. Para isto, cdbxpcmd –list-drives irá listar todos os drivers instalados e um código:

Listar drivers via linha de comando com CD Burner XP

Este código serve para referenciar um drive, exemplo: -drive:0.

Então, o processo é o mesmo porém ao invés de especificarmos -iso iremos especificar o driver desejado -drive:0.

cdbxpcmd --burn-data -folder:"{Caminho da pasta}" -drive:0 -name:"{Nome do disco}" -close

Espero que tenham gostado.