Latest Entries »

Overview
What is BDD? wikipedia
The procedure of BDD should be:
Producure write features file like:
Programmer write code to fill all requirements in the features
Testing. if all features are implemented properly then release. Or back to 2.
BDD using Cucumber, Capybara, PhantomJS
This material is based on this sample project:
git clone https://github.com/fortable1999/BDD-demo.git
Requirement of this tutorial:
We will work on
Sinatra
Cucumber
Capybara
Node.js
Phantom.js
SimpleCov
Make sure Node.js and Phantom.js can be find in your $PATH
Cucumber
Cucumber is a BDD framework.
There are 4 modules in our Sinatra project:
gem ‘sinatra’
gem ‘haml’

gem ‘cucumber’
gem ‘capybara’
gem ‘poltergeist’ # Also, make sure PhantoJS is installed
gem ‘rspec-expectations’

gem ‘simplecov’
Then, use bundle or gem to install:
bundle install

Writing a feature file in features/story1.feature:
#encoding: utf-8

Feature: Viewer vists the page
Test 4 links redirection

Scenario: goto home from home page
Given I am on the home page
When I click “home” link
Then I goto ‘home’ page

Scenario: goto form from page
Given I am on the home page
When I click “form” link
Then I goto ‘form’ page

Scenario: goto success from home page
Given I am on the home page
When I click “success” link
Then I goto ‘success’ page

Scenario: goto error from home page
Given I am on the home page
When I click “error” link
Then I goto ‘error’ page

Generate step function with cucumber:
$ cucumber
#encoding: utf-8
Feature: Viewer vists the page
Test 4 links redirection

Scenario: goto home from home page # features/story1.feature:6
Given I am on the home page # features/story1.feature:7
When I click “home” link # features/story1.feature:8
Then I goto ‘home’ page # features/story1.feature:9

Scenario: goto form from page # features/story1.feature:11
Given I am on the home page # features/story1.feature:12
When I click “form” link # features/story1.feature:13
Then I goto ‘form’ page # features/story1.feature:14

Scenario: goto success from home page # features/story1.feature:16
Given I am on the home page # features/story1.feature:17
When I click “success” link # features/story1.feature:18
Then I goto ‘success’ page # features/story1.feature:19

Scenario: goto error from home page # features/story1.feature:21
Given I am on the home page # features/story1.feature:22
When I click “error” link # features/story1.feature:23
Then I goto ‘error’ page # features/story1.feature:24
4 scenarios (4 undefined)
12 steps (12 undefined)
0m0.022s

You can implement step definitions for undefined steps with these snippets:

Given(/^I am on the home page$/) do
pending # express the regexp above with the code you wish you had
end

When(/^I click “(.*?)” link$/) do |arg1|
pending # express the regexp above with the code you wish you had
end

Then(/^I goto ‘home’ page$/) do
pending # express the regexp above with the code you wish you had
end

Then(/^I goto ‘form’ page$/) do
pending # express the regexp above with the code you wish you had
end

Then(/^I goto ‘success’ page$/) do
pending # express the regexp above with the code you wish you had
end

Then(/^I goto ‘error’ page$/) do
pending # express the regexp above with the code you wish you had
end

Copy these generated code to a step file: features/step_definition/step1.rb,
and modify pending lines like this:
Given(/^I am on the home page$/) do
visit ‘/’
page.should have_content ‘HelloWorld’
end

When(/^I click “(.*?)” link$/) do |arg1|
named_link = arg1
click_link named_link
end

Then(/^I goto ‘form’ page$/) do
current_path.should == ‘/form’
end

Then(/^I goto ‘success’ page$/) do
current_path.should == ‘/success’
end

Then(/^I goto ‘error’ page$/) do
current_path.should == ‘/error’
end

Then(/^I goto ‘home’ page$/) do
current_path.should == ‘/’
end

Run cucumber, get test result:
#encoding: utf-8
Feature: Viewer vists the page
Test 4 links redirection

Scenario: goto home from home page # features/story1.feature:6
Given I am on the home page # features/step_definitions/step1.rb:1
When I click “home” link # features/step_definitions/step1.rb:6
Then I goto ‘home’ page # features/step_definitions/step1.rb:23

Scenario: goto form from page # features/story1.feature:11
Given I am on the home page # features/step_definitions/step1.rb:1
When I click “form” link # features/step_definitions/step1.rb:6
Then I goto ‘form’ page # features/step_definitions/step1.rb:11

Scenario: goto success from home page # features/story1.feature:16
Given I am on the home page # features/step_definitions/step1.rb:1
When I click “success” link # features/step_definitions/step1.rb:6
Then I goto ‘success’ page # features/step_definitions/step1.rb:15

Scenario: goto error from home page # features/story1.feature:21
Given I am on the home page # features/step_definitions/step1.rb:1
When I click “error” link # features/step_definitions/step1.rb:6
Then I goto ‘error’ page # features/step_definitions/step1.rb:19

4 scenarios (4 passed)
12 steps (12 passed)
0m0.825s
Coverage report generated for Cucumber Features to /home/fortable1999/Workspace/RubyEnv/test2/BDD-demo/coverage. 26 / 26 LOC (100.0%) covered.

You can get coverage from ./coverage:
Rakuten Chef Project > Behavior-Driven Development with Cucumber, Capybara, PhantomJS > code_coverage.png

Advertisements

How to quickly start a django project in rails way

Situation:

You want to create a scaffold,
Project’s name is “another”, with a application ‘blogs’ in it,
‘blogs’ application has a model named Post, which has
a string field named ‘title’,
a text field named ‘body’,
a boolean field named ‘is_public’.
You also want a api binded with the Post model.
The application should have full CRUD function(Create, Remove, Update, Detail)

Preparing:

requirement.txt:

Django==1.5.1
Markdown==2.3.1
PIL==1.1.7
PyYAML==3.10
South==0.8.1
defusedxml==0.4.1
django-filter==0.6
-e git://github.com/fortable1999/django-generate-scaffold.git#egg=django_generate_scaffold
django-oauth-plus==2.1.2
django-oauth2-provider==0.2.6
djangorestframework==2.3.6
gunicorn==17.5
httplib2==0.8
oauth2==1.5.211
shortuuid==0.3
wsgiref==0.1.2

save above lines into a requirement.txt file,
then:

pip install -r requirement.txt

Howto:

1. Start a Django project from zero:

django-admin.py startproject another
cd another/

2. Edit setting.py:

vim another/settings.py

Fix here:

'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'dev.db',

uncomment this:

'django.contrib.admin',

add these lines into APPS_INSTALLED:

'generate_scaffold',
'rest_framework',
'south',
'blogs',

add there lines to setting.py:

REST_FRAMEWORK = {
    # Use hyperlinked styles by default.
    # Only used if the `serializer_class` attribute is not set on a view.
    'DEFAULT_MODEL_SERIALIZER_CLASS':
    'rest_framework.serializers.HyperlinkedModelSerializer',
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
        'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

3. Create a empty application:

django-admin.py startapp blogs

6. open a url pattern to application:

vim another/urls.py

uncomment these lines:

from django.contrib import admin
admin.autodiscover()
url(r'^admin/', include(admin.site.urls)),

add there new url pattern:

url(r'^', include('blogs.urls')),

4. create scaffold:

python manage.py generatescaffold blogs Post title:string body:text is_public:bool

5. edit application’s sub urls.py:

vim blogs/urls.py

add there lines after import part:

from django.conf.urls import include
from rest_framework import viewsets, routers
from models import Post
class PostViewSet(viewsets.ModelViewSet): 
    model = Post 
router = routers.DefaultRouter() 
router.register(r'posts', PostViewSet)

then add this into urlpatters:

url(r'api/', include(router.urls)),

6. prepare development envionment database:

python manage.py syncdb
python manage.py schemamigration --initial blogs
python manage.py migrate blogs

7. testing project:

python manage.py runserver

Project done!

References:

Django Rest Framework: http://django-rest-framework.org/
Django generate scaffold: https://github.com/fortable1999/django-generate-scaffold

test

test

django_template_standard

DeleteView

Variables:

  • template_name
  • queryset
  • success_url

Functions:

  • get_queryset
  • get_object
  • delete

Template:

  • object

DatailView
Variables:

  • template_name
  • queryset

Functions:

  • get_object(self, queryset=None)

Template:

  • object

Create View
Variables:

  • template_name
  • initial = {}
  • form_class
  • success_url
  • model
  • queryset

Functions:

  • get_initial
  • get_success_url
  • get_queryset
  • get_object
  • form_valid(form) # important
  • form_invalid(form) # important

Templates:

  • form

class ListView <- (MultipleObjectTemplateResponseMixin, BaseListView)
Variables:

  • template_name # required
  • allow_empty
  • queryset # required

Functions:

  • get_queryset (self)

Template:

  • object_list

my .vimrc

let mapleader = “,”
set nocompatible ” be iMproved
filetype off ” required!

set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

” let Vundle manage Vundle
” required!
Bundle ‘gmarik/vundle’

” My Bundles here:

” original repos on github
Bundle ‘tpope/vim-fugitive’
Bundle ‘Lokaltog/vim-easymotion’
” Bundle ‘tpope/vim-surround’
Bundle ‘tomtom/tcomment_vim’
Bundle ‘vim-scripts/mru.vim’
Bundle ‘msanders/snipmate.vim’
Bundle ‘Raimondi/delimitMate’
Bundle ‘kogakure/vim-sparkup’
Bundle ‘Shougo/neocomplcache’
” Bundle ‘orestis/pysmell’
Bundle ‘rstacruz/sparkup’, {‘rtp’: ‘vim/’}
Bundle ‘tpope/vim-rails.git’
Bundle ‘vim-scripts/taglist.vim’
Bundle ‘vim-scripts/pythoncomplete’
Bundle ‘vim-scripts/FuzzyFinder’
Bundle ‘thinca/vim-localrc’
” Bundle ‘fholgado/minibufexpl.vim’
” Bundle ‘vim-scripts/ShowMarks’
Bundle ‘Lokaltog/vim-powerline’
” Bundle ‘vim-scripts/Pydiction’
” use <leader>pW to call the pythondoc
Bundle ‘fs111/pydoc.vim’
“Bundle ‘vim-scripts/SrcExpl’
Bundle ‘lambdalisue/vim-django-support’
” vim-scripts repos
Bundle ‘L9’

” non github repos
Bundle ‘git://github.com/scrooloose/nerdtree.git’
” Bundle ‘git://git.wincent.com/command-t.git’

filetype plugin indent on ” required!

” Brief help
” :BundleList – list configured bundles
” :BundleInstall(!) – install(update) bundles
” :BundleSearch(!) foo – search(or refresh cache
” first) for foo
” :BundleClean(!) – confirm(or auto-approve)
” removal of unused bundles

” see :h vundle for more details or wiki for FAQ
” NOTE: comments after Bundle command are not allowed..

syntax on
set bs=2
filetype plugin indent on
filetype plugin on
set number

“Configure python stanard indent
set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab

“Configure HTML file indent
autocmd FileType html setlocal tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab

“Configure NERD TREE
nmap <Leader>n :NERDTreeToggle<CR>
let g:NERDTreeDirArrows=0
autocmd vimenter * if !argc() | NERDTree | endif
autocmd bufenter * if (winnr(“$”) == 1 && exists(“b:NERDTreeType”) && b:NERDTreeType == “primary”) | q | endif

“Configure the CTags / taglist.vim:
“make sure you have use ctags command making tags file like
“ctags -R -o ~/.ctags /usr/lib/python2.7/dist-packages /usr/local/lib/python2.7/dist-packages
set tags=~/.ctags
” ——————–
” F4: Switch on/off TagList
nnoremap <silent> <F4> :TlistToggle<CR>
” TagListTagName – Used for tag names
highlight MyTagListTagName gui=bold guifg=Black guibg=Orange
” TagListTagScope – Used for tag scope
highlight MyTagListTagScope gui=NONE guifg=Blue
” TagListTitle – Used for tag titles
highlight MyTagListTitle gui=bold guifg=DarkRed guibg=LightGray
” TagListComment – Used for comments
highlight MyTagListComment guifg=DarkGreen
” TagListFileName – Used for filenames
highlight MyTagListFileName gui=bold guifg=Black guibg=LightBlue
“let Tlist_Ctags_Cmd = $VIM.’/vimfiles/ctags.exe’ ” location of ctags tool
let Tlist_Show_One_File = 1 ” Displaying tags for only one file~
let Tlist_Exit_OnlyWindow = 1 ” if you are the last, kill yourself
let Tlist_Use_Right_Window = 1 ” split to the right side of the screen
let Tlist_Sort_Type = “order” ” sort by order or name
let Tlist_Display_Prototype = 0 ” do not show prototypes and not tags in the taglist window.
let Tlist_Compact_Format = 1 ” Remove extra information and blank lines from the taglist window.
let Tlist_GainFocus_On_ToggleOpen = 1 ” Jump to taglist window on open.
let Tlist_Display_Tag_Scope = 1 ” Show tag scope next to the tag name.
let Tlist_Close_On_Select = 1 ” Close the taglist window when a file or tag is selected.
let Tlist_Enable_Fold_Column = 0 ” Don’t Show the fold indicator column in the taglist window.
let Tlist_WinWidth = 40
” let Tlist_Ctags_Cmd = ‘ctags –c++-kinds=+p –fields=+iaS –extra=+q
“–languages=c++’
” very slow, so I disable this
” let Tlist_Process_File_Always = 1 ” To use the :TlistShowTag and the :TlistShowPrototype commands without the taglist window and the taglist menu, you should set this variable to 1.
“:TlistShowPrototype [filename] [linenumber]”‘

” let Tlist_Show_One_File = 1 ” Displaying tags for only one file~
” let Tlist_Exit_OnlyWindow = 1 ” if you are the last, kill yourself
” let Tlist_Use_Right_Window = 1 ” split to the right side of the screen
” let Tlist_Sort_Type = “order”‘
” let Tlist_Display_Prototype = 0 ” do not show prototypes and not tags in
” the taglist window.
” let Tlist_Compact_Format = 1 ‘
” from the taglist window.
” let Tlist_GainFocus_On_ToggleOpen = 1 ” Jump to taglist window on open.
” let Tlist_Display_Tag_Scope = 1 ” Show tag scope next to the tag name.
” let Tlist_Close_On_Select = 1 ” Close the taglist window when a file or tag
” is selected.
” let Tlist_Enable_Fold_Column = 0 ” Don’
” the taglist window.
” let Tlist_WinWidth = 40
” ” let Tlist_Ctags_Cmd = ‘
” –languages=c++’
” ” very slow, so I disable this
” ” let Tlist_Process_File_Always = 1 ‘
” :TlistShowPrototype commands without the taglist window and the taglist
” menu, you should set this variable to 1.
” “:TlistShowPrototype [“‘
“Configure FuzzyFinder

“Configure NeoComplcache
let g:neocomplcache_enable_at_startup = 1
” let g:neocomplcache_enable_smart_case = 1

“Configure pythoncomplete
“not work very well with external libs.
“but vim-django-support can rescue it.
autocmd FileType python set omnifunc=pythoncomplete#Complete
” if has(“python”)
” python import sys,os
” python sys.path=[]
” python sys.path.append(‘/opt/local/lib/python2.7/site-packages/Twisted-12.1.0-py2.7-macosx-10.4-x86_64.egg/twisted’)
” python sys.path.append(‘/opt/local/lib/python2.7’)
” python sys.path.append(‘/opt/local/lib/python2.7/plat-darwin’)
” python sys.path.append(‘/opt/local/lib/python2.7/plat-mac’)
” python sys.path.append(‘/opt/local/lib/python2.7/plat-mac/lib-scriptpackages’)
” python sys.path.append(‘/opt/local/lib/python2.7/lib-tk’)
” python sys.path.append(‘/opt/local/lib/python2.7/lib-old’)
” python sys.path.append(‘/opt/local/lib/python2.7/lib-dynload’)
” “python os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘djangoProject.settings’
” endif
“Configure pysmell
“As pysmell is a little slower than pythoncomplete,
“Use this carefully.
“autocmd FileType python set omnifunc=pysmell#Complete
autocmd FileType python setlocal omnifunc=pysmell#Complete
“make vim save and load the folding of the document each time it loads”
“”also places the cursor in the last place that it was left.”
” au BufWinLeave * mkview
” au BufWinEnter *.* silent loadview”

“vim will read project.vim in current directory.
“help you write some project specialization configuration
“But this script is replaces the a better plugin:vim-localrc
if filereadable(“project.vim”)
so project.vim
endif

“Configure for django html template snipmate
autocmd FileType html set ft=htmldjango.html

“Configure the code folding:
nnoremap <space> za
vnoremap <space> zf

“Reopen All files when vim runs

“Pydiction path.
” let g:pydiction_location = ‘~/.vim/bundles/Pydiction/complete-dict’
” let g:pydiction_menu_height = 15

“reopen file closed
“nnoremap <esc> :noh<return><esc>
“nmap <esc> nohlsearch

nnoremap zv ^lv$
let g:Powerline_symbols = ‘fancy’

set nowrap

” MRU binding
nnoremap <leader><leader>m :MRU<CR>
nnoremap <leader><leader>M :FufFile<CR>

” Vim as Python IDE hacks
autocmd! bufwritepost .vimrc source %

set mouse=a

noremap <Leader>e :q<CR>
noremap <Leader>E :qa<CR>

map <c-j> <c-w>j
map <c-k> <c-w>k
map <c-h> <c-w>h
map <c-l> <c-w>l

noremap <c-n> :tabNext<CR>
noremap <c-m> :tabnext<CR>

noremap < <gv
noremap > >gv
set nobackup
set nowritebackup
set noswapfile

” Tell vim to remember certain things when we exit
” ” ’10 : marks will be remembered for up to 10 previously edited files
” ” “100 : will save up to 100 lines for each register
” ” :20 : up to 20 lines of command-line history will be remembered
” ” % : saves and restores the buffer list
” ” n… : where to save the viminfo files
set viminfo=’10,\”100,:20,%,n~/.viminfo”‘

function! ResCur()
if line(“‘\””) <= line(“$”)
normal! g`”
return 1
endif
endfunction

augroup resCur
autocmd!
autocmd BufWinEnter * call ResCur()
augroup END

 

references:
http://networklessons.com/linux/openvpn-server-usernamepassword-authentication/

1. Install OpenVPN: use package manager:

Ubuntu:

  apt-get install openvpn udev lzop

CentOS:

  yum install openvpn udev lzop

2. generic key files:

2.1 Move eazy-rsa to /etc/openvpn

  cp -r /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn/

2.2 CA certificate:

  cd /etc/openvpn/easy-rsa/2.0
  source vars
  # if openssl.cnf not found: cp openssl-1.0.0.cnf openssl.cnf
  ./clean-all
  ./build-ca

2.3 Generate server keypair

  ./build-key-server server

2.4 Generate client keypair

  ./build-key-server client1

2.5 Generate Diffie-Hellman key

  ./build-dh

3. Configuration

3.1 Server side configuration:

local 
port 
proto 
dev tun
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.crt
key /etc/openvpn/keys/server.key
dh /etc/openvpn/keys/dh1024.pem
ifconfig-pool-persist ipp.txt
server 10.8.1.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
client-to-client
duplicate-cn
keepalive 20 120
comp-lzo
max-clients 50
persist-key
persist-tun
status openvpn-status.log
log-append openvpn.log
verb 3
mute 20

3.2 Client site configuration:

client
dev tun
proto udp
remote 163.43.141.40 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
ns-cert-type server
redirect-gateway
keepalive 20 60
#tls-auth ta.key 1
comp-lzo
verb 3
mute 20
route-method exe
route-delay 2

4. iptables configureation:

#!/bin/sh
/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -j SNAT --to-source 
/sbin/iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -o eth0 -j MASQUERADE
/sbin/iptables -I INPUT -p tcp --dport 443 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -I FORWARD -s 10.8.0.0/16 -j ACCEPT
/sbin/iptables -I INPUT -i lo -j ACCEPT
/sbin/iptables -I INPUT -i tun0 -j ACCEPT
/sbin/iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

5. Change sysctl.conf:

  net.ipv4.ip_forward = 1
  net.ipv4.conf.all.send_redirects = 0
  net.ipv4.conf.default.send_redirects = 0
  net.ipv4.conf.all.accept_redirects = 0
  net.ipv4.conf.default.accept_redirects = 0
  sysctl -p

6. Restart network

  /etc/init.d/openvpn restart
  /etc/init.d/networking restart

View full article »