├── practices
├── react.md
├── ios.md
├── javascript.md
├── design.md
├── README.md
├── git.md
├── issues.md
├── ember.md
├── react-redux.md
├── react-native.md
├── rails.md
├── qa.md
├── i18n.md
└── testing.md
├── watch
└── README.md
├── workflow
├── android-osx.md
├── rails-osx.md
├── heroku.md
├── elixir.md
├── rails-ubuntu1404.md
└── ios.md
├── README.md
├── tools
└── README.md
└── read
└── README.md
/practices/react.md:
--------------------------------------------------------------------------------
1 | # React
2 |
--------------------------------------------------------------------------------
/practices/ios.md:
--------------------------------------------------------------------------------
1 | # iOS
2 |
3 | - Follow the [Ray Wenderlich Styleguide](https://github.com/raywenderlich/swift-style-guide) except using 2 spaces as indentation. We'll use 4 spaces as recommended by Apple.
4 | - Prefer [realm.io](http://realm.io) over CoreData.
5 | - Use CocoaPods whenever available. When you need a library/plugin, check [Cocoa Controls](https://www.cocoacontrols.com/) first before trying to do it yourself.
6 |
--------------------------------------------------------------------------------
/practices/javascript.md:
--------------------------------------------------------------------------------
1 | # JavaScript
2 |
3 | - Follow [airbnb/javascript](https://github.com/airbnb/javascript) the styleguide (feel free to discard ES6-isms for non-ES6 projects)
4 | - Follow [rsjs](https://github.com/rstacruz/rsjs)'s guideline on behaviors
5 | - Prefer [babel](http://babeljs.io/) as a preprocessor. For rails, use [sprockets-es6](https://rubygems.org/gems/sprockets-es6)
6 |
7 | Avoid:
8 |
9 | - Avoid [coffeescript](http://coffeescript.org/). See above
10 |
--------------------------------------------------------------------------------
/watch/README.md:
--------------------------------------------------------------------------------
1 | ## Design
2 |
3 | - [Aaron Draplin on Logo Design](https://vimeo.com/113751583) - on logo design iterations
4 | - [The Design Sprint: from Google Ventures to Google](https://www.youtube.com/watch?v=aWQUSiOZ0x8) - on design sprint
5 | - [The History of Typography](https://www.youtube.com/watch?v=wOgIkxAfJsk) - on type
6 | - [How to Build Your Creative Confidence](https://www.youtube.com/watch?v=16p9YRF0l-g) - on motivation lol
7 | - [Bootstrap 4 Grid System](http://designmodo.com/bootstrap-4-grid-system/) - explaining Bootstrap's grids
8 |
9 | ## Development
10 | - [Nothing is Something by Sandi Metz](https://www.youtube.com/watch?v=OMPfEXIlTVE) - on nil objects
11 | - [Architecture the Lost Years by Robert Martin](https://www.youtube.com/watch?v=WpkDN78P884) - on architecture
12 | - [All the Little Things by Sandi Metz](https://www.youtube.com/watch?v=8bZh5LMaSmEA) - on small, interchangeable objects
13 |
--------------------------------------------------------------------------------
/workflow/android-osx.md:
--------------------------------------------------------------------------------
1 | # Basic OS X Machine Setup for Android Development
2 |
3 | ## Easy mode
4 |
5 | If you have [Homebrew](http://brew.sh/) and [Homebrew Cask](https://caskroom.github.io/):
6 |
7 | ```sh
8 | brew cask install java
9 | brew cask install android-studio
10 | ```
11 |
12 | Tested on El Capitan (OS X 10.11). You may also check out these brew packages: `android-sdk` (standalone SDK without studio), `android-platform-tools` (adb and friends).
13 |
14 | ## Manual setup
15 |
16 | > NB: These instructions are dated May 2015 and are for OS X 10.10.
17 |
18 | ####Pre-requisites
19 | 1. Update to Yosemite(OS X 10.10) from App Store
20 | 2. Install latest JRE at http://www.oracle.com/technetwork/java/javase/downloads/index.html
21 | 3. Android Studio still have dibs for Java 6 for its font rendering not to mention certain bugs with the latest OS X; Download this support patch https://support.apple.com/kb/DL1572 and install
22 |
23 | ####Setup Android Studio
24 | 1. Download and install it http://developer.android.com/sdk/index.html
25 | 2. Run Android Studio and follow throught the steps which includes downloading the rest of the dependencies such as Android SDK
26 |
--------------------------------------------------------------------------------
/practices/design.md:
--------------------------------------------------------------------------------
1 | # Design practices
2 |
3 | ## Design
4 |
5 | - Prefer [Sketch](http://bohemiancoding.com/sketch/) for UI design
6 | - Prefer [ionicons](http://ionicons.com/) for UI icons (instead of FontAwesome)
7 | - Prefer [Styledown](https://github.com/styledown/styledown) for making a Living Styleguide
8 |
9 | ## Sass/CSS
10 |
11 | - Prefer `.scss` (nested) syntax over `.sass` (indented), since most projects use that
12 | - Enable [CSS antialiasing](http://ricostacruz.com/cheatsheets/css-antialias) globally
13 | - Prefer to make new components rather to extend/override Bootstrap components
14 | - Prefer to break CSS into multiple files and use `@import 'components/*'` ([info](https://github.com/rstacruz/rscss#one-component-per-file))
15 | - Prefer to start a styleguide as early on in the project
16 | - Refer to [rscss](http://rscss.io)
17 | - The rscss [two-word rule](https://github.com/rstacruz/rscss#naming-components) isn't generally followed around here, feel free to break it
18 | - Style `&:focus, &:hover { ... }` together
19 | - If you've never broken the rule above, feel free to use `:focus { outline: none }` ([haha](http://www.outlinenone.com/))
20 |
21 | ## Bootstrap
22 |
23 | - Refer to [bootstrap-practices](https://github.com/rstacruz/bootstrap-practices)
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :cloud: Awesome
2 |
3 | ### Our practices
4 | This is a list of things to prefer and avoid in projects. These practices are a result of trials-and-errors across many [Proudcloud] projects. We've learned what works and what doesn't, and these are the lessons that stuck.
5 |
6 | - [General practices](practices/) - ethics, new projects
7 | - [Design](practices/design.md) - UI design and CSS
8 | - [Git](practices/git.md) - Git and GitHub
9 | - [JavaScript](practices/javascript.md) - Frontend and Node.js code
10 | - [Rails](practices/rails.md) - Makes the world go 'round
11 | - [Testing](practices/testing.md) - Detailed Rspec and TDD practices
12 | - [iOS](practices/ios.md) - Xcode Swift development
13 | - [i18n](practices/i18n.md) - Rails localization
14 | - [Ember](practices/ember.md) - SPA Development with Ember.js
15 | - [Issues](practices/issues.md) - Filing issues
16 |
17 | ----
18 |
19 | ### Required reading
20 | Must-read books, articles and must-watch videos for every [Proudcloud] developer.
21 |
22 | - [Required reading](read/README.md)
23 |
24 | ----
25 |
26 | ### Workflow
27 | Guides on setting up common development environments.
28 |
29 | - [Android on OSX](workflow/android-osx.md)
30 | - [Elixir](workflow/elixir.md)
31 | - [Heroku](workflow/heroku.md)
32 | - [Rails on OSX](workflow/rails-osx.md)
33 | - [iOS](workflow/ios.md)
34 | - [Rails on Ubuntu 14.04](workflow/rails-ubuntu1404.md)
35 |
36 | ----
37 |
38 | ### Tools
39 | A list of our recommended tools for design and development.
40 |
41 | - [Tools](tools/README.md)
42 |
43 | [Proudcloud]: http://proudcloud.net
44 |
45 |
46 |
47 | ----
48 |
49 | :copyright: 2015, [Proudcloud]. Released under MIT License.
50 | Feel free to reuse this list for your own team!
51 |
--------------------------------------------------------------------------------
/practices/README.md:
--------------------------------------------------------------------------------
1 | # Development practices
2 |
3 | This is a list of things to prefer and avoid in projects. These practices are a result of trials-and-errors across many Proudcloud projects. We've learned what works and what doesn't, and these are the lessons that stuck.
4 |
5 | ## Ethics
6 |
7 | - Always be online on Slack
8 | - Better to ask forgiveness than permission
9 | - Respect your team and individual schedules
10 | - Always work on targeted release versions or milestones. We use `alpha`, `beta` for early stage projects. Moving forward, practice the use of [Semantic Versioning](http://semver.org).
11 | - Be aware of the product roadmap.
12 | - Work will never run out. Focus on approximately 2 weeks (1 sprint) worth of targets only. Close a version release. Repeat the cycle.
13 | - Conserve energy. Do not overwork yourselves.
14 | - Code clarity. Readable code.
15 | - Consistency with team practices but feel free to discuss improvements.
16 | - Consistency but correct and raise what you feel is wrong.
17 | - Do your best not to be a blocker to your teammates.
18 | - Got a problem? Ask on Slack.
19 |
20 | ## Starting a new project
21 |
22 | - Create a Github repo and make the default branch to `develop`.
23 | - Create and update the project's `README.md`
24 | - Add proper installation instructions. Notes and caveats.
25 | - Github Slack channel integration. The amount of notifications you want to receive depends on you. Usually, we like to get notified with new pull requests and comments only.
26 | - Continuous integration. Currently, we're using [Circleci](https://circleci.com). Ask an organization admin or a collaborator to add it for you if you don't have access. Circleci uses Github authentication so you don't need an invite. Don't forget the Slack integration.
27 |
28 | ## Watch out
29 |
30 | 
31 |
32 |
--------------------------------------------------------------------------------
/practices/git.md:
--------------------------------------------------------------------------------
1 | # Git
2 |
3 | Using GitHub:
4 |
5 | - Send pull requests for code review. Tag it with `review` when you're done
6 | - Be overly communicative about your pull requests. Best practice is to add screenshots to your pull requests ([example](https://github.com/proudcloud/crowd-funding/pull/371)) for your reviewer's convenience.
7 | - Long running PRs are welcome. Always get your branches checked against the main branch (usually `develop`)
8 | - Get your PRs updated. Rebase on top of the latest `develop` branch.
9 | - If your PR references a Github Issue, make sure to mention it in your PR's description using [this format ](https://help.github.com/articles/closing-issues-via-commit-messages/).
10 |
11 | Git:
12 |
13 | - Always commit. Small commits are acceptable.
14 | - Make your commits contextual. Avoid commits that does other things that the commit was intended to.
15 | - Commit messages that makes sense. Usually in this pattern: `"{action} {purpose|reason} {target}"`, order may vary.
16 |
17 | Avoid:
18 | ```
19 | 1) "Adds price validation"
20 | 2) "Refactors the decorator"
21 | 3) "Fixes bug"
22 | 4) "Hotfix for the form bug"
23 | ```
24 |
25 | Ideal:
26 | ```
27 | 1) "Adds price validation to Product"
28 | 2) "Refactors product.total_price decorator"
29 | 3) "Fixes permitted params bug on orders#create"
30 | 4) "Hotfix for the product form's price input bug"
31 | ```
32 |
33 | [Here's an example of a good PR and commit](https://github.com/proudcloud/crowd-funding/pull/371)
34 |
35 | - Target as the most important as without it `"Fixes bug"`, `"Adds price validation"` or `"Refactors"` doesn't actually make sense if people review the project commit history.
36 | - Always delete `merged`, `stale`, `outdated` branches. *Ang past ay para sa mga bitter lamang. Wag clingy.* [1](https://github.com/proudcloud/awesome/issues/23#issuecomment-108285010)
37 |
38 | Branching:
39 |
40 | - Use `feature/xyz` branches for features, `fix/xyz` for code fixes, `hotfix/xyz` for emergency hotfixes (see [git-flow])
41 | - Use the `develop` branch for development
42 | - Use the `master` branch for deployable versions
43 | - Make sure `develop` is always passing CI tests
44 | - Make sure `master` is always at a deployable state
45 |
46 | Avoid:
47 |
48 | - Avoid `production` branches, they're usually the same as master
49 |
50 | [git-flow]: http://nvie.com/posts/a-successful-git-branching-model/
51 |
--------------------------------------------------------------------------------
/practices/issues.md:
--------------------------------------------------------------------------------
1 | # Writing issues
2 |
3 | When filing issues, keep the title short and the body descriptive.
4 |
5 |
6 |
7 | ## Titles
8 |
9 | * **Keep the title short.**
10 | Put any details in the body, not in the title. This makes it easier to digest a long list of issues.
11 |
12 | > `When I try to change passwords, an error is raised.` ✗ *...can be shorter*
13 | > `[User] can't change passwords` ✗ *...put that in the description*
14 | > `Can't change passwords` :+1:
15 |
16 | * **Don't be too general.**
17 | Try to be more specific when possible.
18 |
19 | > `Products error` ✗ *...too broad*
20 | > `Can't buy products` ✗ *...still too broad*
21 | > `Product page error` ✗ *...still too broad*
22 | > `Product page: the buy button isn't clickable` :+1:
23 |
24 |
25 |
26 | ## Details
27 |
28 | * **Write a short description.**
29 | Add a one-sentence (or one-paragraph) in the body of the issue.
30 |
31 | >
32 | > Title: `Can't change passwords`
33 | > Description:
34 | > `When I'm logged into as a User, the "change email" form returns an error.`
35 |
36 | * **Be visual.**
37 | Include screenshots when possible!
38 |
39 | * **Be detailed.**
40 | For bug reports, ensure that the following details are available or are obvious:
41 |
42 | * URL *(if applicable)*
43 | * Environment *(OS, browser, website environment)*
44 | * Steps to reproduce
45 | * Expected result
46 | * Actual result
47 |
48 | * **But not too detailed.**
49 | You don't need to actually list *all* of them (especially for simple issues), just make sure that anyone can figure those details out.
50 |
51 |
52 |
53 | ## Short example
54 | No need to include steps/expected/actual when it's obvious.
55 |
56 | > **Avatars are not shown**
57 | > The user directory is missing avatars. (OS X, Firefox, Production)
58 | > http://ticketadvisor.com/users
59 | >
60 | > `[screenshot goes here]`
61 |
62 | ## Full example
63 |
64 | > **Can't send email**
65 | > The "send email" button isn't clickable.
66 | > Environment: OS X, Firefox, Production.
67 | > http://ticketadvisor.com/user/23/edit
68 |
69 | > `[screenshot goes here]`
70 |
71 | > Steps:
72 | 1. Log in as a user
73 | 2. Go to the Inbox page
74 | 3. Click "write new email"
75 | 4. Click "send"
76 |
77 | > Expected: The email will be sent.
78 | > Actual: A JavaScript error appears when "send" is clicked.
79 |
--------------------------------------------------------------------------------
/practices/ember.md:
--------------------------------------------------------------------------------
1 | # Ember
2 |
3 | ##Development
4 |
5 | ###Tools
6 | - [Ember-cli](http://www.ember-cli.com/) for project management
7 | - [ES2015/Babel](https://babeljs.io/) as our JS flavor
8 | - [Sass](http://sass-lang.com/) as our CSS flavor
9 | - [Emblem](http://emblemjs.com/) for templates
10 | - [Ember-data](https://github.com/emberjs/data) for data management
11 |
12 | ###Practices
13 | - Favor [Ember Object Model](http://guides.emberjs.com/v1.11.0/object-model/classes-and-instances/) over plain javascript
14 |
15 | ####Routes
16 | - Ember routes are tightly coupled with view rendering, but let's maintain restful routing as much as possible
17 |
18 | ####Models
19 | - Use [ActiveModel Adapter](http://emberjs.com/api/data/classes/DS.ActiveModelAdapter.html) for data serialization/deserialization
20 | - Load data in store as needed
21 | - Set relationships as async true as needed (be mindful that setting relationships as async true changes the behavior of certain functions)
22 |
23 | ```javascript
24 | //in models/sample.js
25 | export default DS.Model.extend({
26 | sampleRelationship: DS.belongsTo('anotherModel', {async: true}),
27 | });
28 |
29 | sampleInstance.get('sampleRelationship'); //Will return a promise object
30 |
31 | //set to async:false
32 | sampleInstance.get('sampleRelationship') //Will return the model
33 |
34 | ```
35 |
36 | ####Controllers
37 | - Keep application level logic in controllers.
38 |
39 | ```javascript
40 | //route transitions
41 | this.transitionToRoute('sample.route');
42 |
43 | //data manipulation
44 | sampleModel.save();
45 | sampleModel.destroy();
46 |
47 | //ajax requests
48 | Ember.$.ajax('/sample_url');
49 | ```
50 |
51 | - Keep api requests logic in one mixin/class and just require it in controllers as needed.
52 |
53 | ####Templates
54 |
55 | ####Components
56 | - favor components over views
57 | - always declare your component's name in its classNames property
58 |
59 | ```javascript
60 | //in sample-component.js
61 | export default Ember.Component.extend({
62 | classNames: ['sample-component']
63 | });
64 | ```
65 |
66 | - always declare layout related classes in component instantation
67 |
68 | ```javascript
69 | //in sample-component.js
70 | export default Ember.Component.extend({
71 | //Don't do this
72 | classNames: ['sample-component', 'col-md-5']
73 | });
74 |
75 | //instead do it this way
76 | //in page.emblem
77 | sample-component class='col-md-5'
78 | ```
79 |
80 | - Avoid application level logic here
81 |
82 | ##Helpful Resources
83 | - ember-cli 101 by Adolfo Builes
84 | - Ember [Blog](http://emberjs.com/blog/) - Ember is in active development, we need to sync our practices with new trends.
85 |
--------------------------------------------------------------------------------
/workflow/rails-osx.md:
--------------------------------------------------------------------------------
1 | # Basic OS X Machine Setup for RoR Development
2 | ####Pre-requisites
3 | 1. Update to Yosemite(OSX 10.10) from App Store
4 |
5 | 2. Install xCode 6.x
6 | 3. Install xCode Command Line Tools
7 | ```
8 | $ xcode-select --install
9 | ```
10 | 4. Install Homebrew & update packages
11 | ```
12 | $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
13 | $ brew update
14 | ```
15 | 5. Verify Homebrew installation
16 | ```
17 | $ brew doctor
18 | ```
19 |
20 | ####Setup Git, Homebrew, RVM, & Default Ruby & Gemset
21 | Run GCC then confirm appropriate root privileges
22 | ```
23 | $ sudo gcc --version
24 | ```
25 | Setup initial git config
26 | ```
27 | $ git config --global user.name "Your Real Name"
28 | $ git config --global user.email me@example.com
29 | $ git config -l --global
30 | ```
31 | Add SSH key
32 | ```
33 | $ ssh-keygen -t rsa -C "YOUR@EMAIL.com"
34 | ```
35 | Or copy from existing; create directory
36 | ```
37 | $ mkdir ~/.ssh
38 | $ cp ~/Downloads/id_rsa ~/.ssh
39 | $ cp ~/Downloads/id_rsa.pub ~/.ssh
40 | ```
41 | Install RVM and follow additional procedure such as sourcing RVM to profile
42 | ```
43 | $ \curl -L https://get.rvm.io | bash -s stable --ruby
44 | ```
45 | Install latest or appropriate ruby version
46 | ```
47 | $ rvm install ruby
48 | $ rvm --default use ruby-2.2.0
49 | ```
50 | For faster bundling
51 | ```
52 | $ echo "gem: --no-ri --no-rdoc" >> ~/.gemrc
53 | ```
54 | Double ruby version and gemset (default) is active then install
55 | ```
56 | $ gem install rails
57 | ```
58 |
59 | ####Install PostgreSQL
60 | ```
61 | $ brew install postgresql
62 | ```
63 | > Caveats: If builds of PostgreSQL 9 are failing and you have version 8.x installed, you may need to remove the previous version first. See:
64 | https://github.com/Homebrew/homebrew/issues/2510
65 |
66 | > To migrate existing data from a previous major version (pre-9.4) of PostgreSQL, see:
67 | http://www.postgresql.org/docs/9.4/static/upgrading.html
68 |
69 | To have launchd start postgresql at login
70 | ```
71 | $ ln -sfv /usr/local/opt/postgresql/*.plist ~/Library/LaunchAgents
72 | ```
73 | Then to load postgresql now
74 | ```
75 | $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
76 | ```
77 | Or, if you don't want/need launchctl, you can just run
78 | ```
79 | $ postgres -D /usr/local/var/postgres
80 | ```
81 | You can check back this info by
82 | ```
83 | $ brew info postgresql
84 | ```
85 |
86 | #### Install MongoDB
87 | $ brew install mongodb
88 | To have launchd start mongodb at login:
89 | ```
90 | $ ln -sfv /usr/local/opt/mongodb/*.plist ~/Library/LaunchAgents
91 | ```
92 | Then to load mongodb now
93 | ```
94 | $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist
95 | ```
96 | Or, if you don't want/need launchctl, you can just run
97 | ```
98 | $ mongod --config /usr/local/etc/mongod.conf
99 | ```
--------------------------------------------------------------------------------
/workflow/heroku.md:
--------------------------------------------------------------------------------
1 | # Heroku Deployment for Rails
2 | ####Pre-requisites:
3 | - Existing Rails App
4 | - Git & associated SSH Keys
5 | ```
6 | # If app isn't associated with git yet
7 | $ git init
8 | $ git add .
9 | $ git commit -m 'Sets initial commit'
10 | ```
11 | ```
12 | # If no SSH Keys generated yet, run command below;
13 | # Fill-in succeeding prompts as desired but leave out passphrase prompt as empty
14 | $ ssh-keygen -t rsa
15 | ```
16 | - Heroku Account. Sign up [here].
17 | - Heroku Toolbelt
18 | ```
19 | # OSX (via Homebrew)
20 | $ brew install heroku-toolbelt
21 | # Debian/Ubuntu
22 | $ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh
23 | # Login
24 | $ heroku login
25 | ```
26 |
27 |
28 | ####Setup:
29 | Specify ruby version in your `Gemfile`. This is clearly ok unless you indicate a different version from that of your `.ruby-version` et al
30 | ```
31 | source "https://rubygems.org"
32 | ruby "2.1.2"
33 | # ...
34 | ```
35 | Set static asset serving at `config/application.rb`
36 | ```
37 | config.serve_static_files = true
38 | ```
39 | It is expected that credentials/keys are set in your `secrets.yml`(which is included in the repo), just make sure the these are appropriately set within `production: ` block as well
40 | ```
41 | production:
42 | secret_key_base: 320f4772bb7e84f94f83b05a1e220d6b18c3053e4d601224efbda34434a79183e0f721a7b12c0ae89a91b9eaba092ceba8f145ddb4fd46dc9016fed6202e5a41
43 | ...
44 | development:
45 | secret_key_base: 769579477b78657f832f260b62151d8955b3f3bcdd054cc287d17fe0c75a7524f0d8a07c733c55acbe72e1ce8821e1ef11739a14e525a8443129d26742a10f1f
46 | ...
47 | ```
48 | Set DB-related configurations differ depending on the DB you are using. If you're on `PostgreSQL`, a simple `heroku run rake db:migrate` will do.
49 |
50 | If you're using `mongoid`, I prefer [MongoLab] as a starting point
51 |
52 | Create Heroku app/instance
53 | ```
54 | $ heroku apps:create my-very-own-project-such-wow
55 | ```
56 | Push to Heroku
57 | ```
58 | $ git push heroku master
59 | ```
60 |
61 | Open your app deployed from Heroku
62 | ```
63 | $ heroku open
64 | ```
65 | ****
66 |
67 |
68 | ####After all this...
69 | ...why not add `rail_12factor` gem to Gemfile? *If you're not concerned with Rails logs being written to file, `config.serve_static_assets = true` is all you need.*
70 |
71 | ...I use `secrets.yml` instead of `application.yml`? *It's a known limitation for using Heroku. Best stick in using `ENV[___]` approach on this one.*
72 |
73 | ...why not set `RAILS_ENV=staging` instead of `production` at my Heroku instance? *1) Dev/Prod Parity; get your prod environment as close as that with your local one by minimizing enviroment-related differences on variables for example, also, 2) it is unlikely that you want a real production app deployed at Heroku.*
74 |
75 | ...why not use `Figaro` for environment variables? *Just use `heroku config:set`*
76 |
77 | ...why not use `Foreman`? *Use it, then!*
78 |
79 | [here]:https://www.heroku.com/
80 | [MongoLab]:https://devcenter.heroku.com/articles/mongolab
--------------------------------------------------------------------------------
/tools/README.md:
--------------------------------------------------------------------------------
1 | # Recommended tools
2 |
3 | ## Code Editors
4 |
5 | - [Vim](http://vim.org/)
6 | - [Atom](https://atom.io/)
7 | - [Emacs](https://www.gnu.org/software/emacs/) with [Spacemacs](https://github.com/syl20bnr/spacemacs) _(actually, only Vic uses this)_
8 |
9 | ## Vim plugins
10 |
11 | - [neomake](https://github.com/neomake/neomake) - a plugin for asynchronous :make using Neovim's job-control functionality
12 | - [vim-commentary](https://github.com/tpope/vim-commentary) - comment stuff out
13 | - [vim-plug](https://github.com/junegunn/vim-plug) - a minimalist Vim plugin manager
14 | - [vim-surround](https://github.com/tpope/vim-surround) - quoting/parenthesizing made simple
15 | - [YouCompleteMe](https://github.com/Valloric/YouCompleteMe) - a code-completion engine for Vim
16 |
17 | ## Sketch plugins
18 |
19 | - [Sketch Toolbox](https://github.com/buzzfeed/Sketch-Toolbox) - installs sketch plugins for you
20 | - [Invision Craft](https://www.invisionapp.com/craft) - placeholder text and more
21 | - [Clipboard Fill](https://github.com/ScottSavarie/Clipboard-Fill) - paste images as a fill
22 |
23 | ## GIF recorders
24 |
25 | - [LICEcap](http://www.cockos.com/licecap/) (free, OSX, Win) - records to .gif locally
26 | - [Gyazo GIF](https://gyazo.com/) (freemium, OSX, Win, Linux) - records and uploads to the cloud. hosting limited to 10 images/month ($3.99/mo to unlock)
27 | - [Recordit](http://recordit.co/) (freemium, OSX, Win) - records and uploads to the cloud. unlock private recordings and higher FPS with the pro version for $29
28 | - [CloudApp](https://www.getcloudapp.com/) (freemium, OSX) - limited to 10 files ($10/mo to unlock)
29 | - [Claquette](https://www.peakstep.com/claquette/) $9.99 with addons for more export options
30 |
31 | ## OSX (Design)
32 |
33 | - [Sip](http://sipapp.io/) (freemium) - color picker
34 | - [Adobe Creative Cloud](https://creative.adobe.com/products/creative-cloud) (free) - for TypeKit fonts on your computer
35 |
36 | ## Chrome extensions
37 |
38 | - [Vimium](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en) - Vim on Chrome
39 | - [JSONView](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en) - Format JSON responses
40 | - [EyeDropper](https://chrome.google.com/webstore/detail/eye-dropper/hmdcmlfkchdmnmnmheododdhjedfccka) - Colorpicker
41 | - [Panda](https://usepanda.com/) - Newsfeed Dashboard for Design and Development
42 | - [WhatFont](https://chrome.google.com/webstore/detail/whatfont/jabopobgcpjmedljpbcaablpmlmfcogm?hl=en) - Easiest to identify fonts in web pages
43 | - [Window Resizer](https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh?hl=en) - Resize browser window to emulate various screen resolutions
44 | - [Raindrop](http://raindrop.io/extension/) - For bookmarks
45 |
46 | ## How to add to this list
47 |
48 | - Send a PR.
49 | - Have someone +1 it—we won't add something just because you use it! Unless you're Vic.
50 | - Bug for someone not to be too lazy to merge your PR
51 |
--------------------------------------------------------------------------------
/practices/react-redux.md:
--------------------------------------------------------------------------------
1 | # React Redux
2 |
3 | ## Containers vs. Components
4 |
5 | Separate your containers from your components.
6 |
7 | - Containers are smart components. They do data-fetching and pass it to components.
8 | - Components are dumb and reliant to containers for their data. Since they are relaint to containers, they can be reused in other containers.
9 |
10 | See: [Making your app fast with high-performance components by Jason Bonta](https://youtu.be/KYzlpRvWZ6c?t=22m49s)
11 |
12 | ## Suggested File structure
13 |
14 | The suggested file structure is based on @adimasuhid's idea. If you have a directory and it was removed, the app should be still functional or needs minimal changes to make it work.
15 |
16 | This also allows reusable features through other applications such as `chat` and `filtering`.
17 |
18 | ```
19 | react
20 | └───(Feature)
21 | │ └───components
22 | │ └───containers
23 | │ │ actions.jsx - action creator functions
24 | │ │ actionTypes.jsx
25 | │ │ apiWrappers.jsx
26 | │ │ reducer.jsx - reducer to be used in the store
27 | │ │ propTypes.jsx - reusable proptypes
28 | └───(Shared Components)
29 | └───App.jsx - main entrypoint
30 | └───configureStore.jsx - store builder
31 | └───DevTools.jsx
32 | └───rootReducer.jsx
33 | ```
34 |
35 | ## `mapStateToProps`, `mapDispatchToProps` and `connect`
36 |
37 | There are some examples in the `redux` repository that show you can use a function for getting the object needed for `mapStateToProps`. We recommend that you use this example below for verbosity.
38 |
39 | ```js
40 | const mapStateToProps = (state) => {
41 | return {
42 | component: state.component.attribute
43 | }
44 | }
45 | ```
46 |
47 | `mapDispatchToProps` can be omitted unless you want to. It can be written like this:
48 |
49 | ```js
50 | const mapDispatchToProps = (dispatch) => {
51 | return {
52 | function: () => { namedFunction() }
53 | }
54 | }
55 |
56 | export default connect(
57 | mapStateToProps,
58 | mapDispatchToProps
59 | )(Container)
60 | ```
61 |
62 | or
63 |
64 | ```js
65 | export default connect(
66 | mapStateToProps,
67 | { namedFunction }
68 | )(Container)
69 | ```
70 |
71 | ## Configuring the Store
72 |
73 | The `compose` function allows you to add different middlewares such as `redux-thunk` and `redux-devtools`.
74 |
75 | ```js
76 | export default configureStore(initialState = {}, environment) => {
77 | const store = createStore(
78 | rootReducer,
79 | initialState,
80 | compose(
81 | applyMiddleware(thunk)
82 | )
83 | )
84 | }
85 | ```
86 |
87 | Here are some middlewares you might want to check out:
88 | - [redux-thunk](https://github.com/gaearon/redux-thunk)
89 | - [redux-saga](https://github.com/yelouafi/redux-saga)
90 | - [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware)
91 |
92 | See [this StackOverflow answer](http://stackoverflow.com/questions/36577510/what-is-the-difference-between-redux-thunk-and-redux-promise) on the difference between redux-thunk and redux-promise.
93 |
--------------------------------------------------------------------------------
/practices/react-native.md:
--------------------------------------------------------------------------------
1 | # React Native
2 |
3 | This is a collection of (best?) practices when developing React Native apps--the Proudcloud way.
4 |
5 | Basic prerequisites of developing React Native apps include [React](https://facebook.github.io/react/)
6 | and [Redux](http://redux.js.org/). If you don't even have a slightest clue on what you're doing, STOP.
7 | Please do us a favor: read [Thinking In React](https://facebook.github.io/react/docs/thinking-in-react)
8 | and create sample apps before even jumping on-board a project. This will save us time spent on nonsense
9 | code reviews.
10 |
11 | ## Proposed File Structure
12 |
13 | Given that we have a Blog app with basic CRUD functionalities, below is its proposed file structure:
14 |
15 | ```
16 | project
17 | `- android - Android Studio project
18 | `- ios - Xcode project
19 | `- js
20 | `- actions
21 | `- post.js
22 | `- user.js
23 | `- assets
24 | `- fonts
25 | `- images
26 | `- ...
27 | `- components
28 | `- common - Shared components like forms, buttons, etc.
29 | `- Button.js
30 | `- FacebookButton.js
31 | `- ...
32 | `- PostList.js
33 | `- PostDetails.js
34 | `- RegistrationForm.js
35 | `- LoginForm.js
36 | `- ...
37 | `- config
38 | `- index.js - You can probably load environment variables in this file
39 | `- facebook.js - Sample Facebook-related config. You can load this in config/index.js
40 | `- containers
41 | `- posts
42 | `- New.js
43 | `- Edit.js
44 | `- List.js
45 | `- sessions
46 | `- Registration.js
47 | `- Login.js
48 | `- reducers
49 | `- index.js - This is the root reducer
50 | `- posts.js
51 | `- users.js
52 | `- store
53 | `- configureStore.js
54 | `- utils - Any utility classes/helpers go here
55 | App(.ios/.android).js - Main React class. Omit .ios or .android as necessary
56 | `- node_modules
57 | index.android.js
58 | index.ios.js
59 | package.json
60 | ```
61 |
62 | ## Containers vs. Components
63 |
64 | As mentioned in https://github.com/proudcloud/awesome/blob/master/practices/react-redux.md
65 |
66 | > Separate your containers from your components.
67 |
68 | > - Containers are smart components. They do data-fetching and pass it to components.
69 | > - Components are dumb and reliant to containers for their data. Since they are relaint to containers, they can be reused in other containers.
70 |
71 | > See: [Making your app fast with high-performance components by Jason Bonta](https://youtu.be/KYzlpRvWZ6c?t=22m49s)
72 |
73 | Or in iOS Development terms, think of Containers as View Controllers and Components as separate Views.
74 |
75 |
76 | ## Further Reading
77 |
78 | Here are great articles for further reading:
79 | - [React Native Getting Tutorial](https://facebook.github.io/react-native/docs/tutorial.html)
80 | - [React Native Awesome](https://github.com/enaqx/awesome-react#react-native)
81 | - [Building the F8 2016 App](http://makeitopen.com/)
82 | - [Preview your React Native apps in your Github Pull Request](http://tech.m6web.fr/preview-android-ios-react-native-on-github-pull-request/)
83 |
84 |
85 | ## Deep Dive
86 |
87 | If you need a good jumpstart, try following [Building the F8 2016 App](http://makeitopen.com/).
88 | It's a great starting point for begginers and a good refresher for intermediate React Native developers.
89 |
--------------------------------------------------------------------------------
/workflow/elixir.md:
--------------------------------------------------------------------------------
1 | # Setup for Elixir projects
2 |
3 | It's mostly the same as setting up environments for Ruby or JavaScript, with some nuances:
4 |
5 | - [Postgres](#postgres): to make your life easier, create a user with name `postgres` password `postgres`. This is the default for most Phoenix projects.
6 | - [Asdf](#asdf): this is the preferred version manager for Elixir, Erlang and Node.js.
7 |
8 | All of these steps are optional, but recommended.
9 |
10 |
11 |
12 | ## Postgres
13 |
14 | > Phoenix projects default to connecting to Postgres with the username `postgres` and password `postgres`. This isn't so easy to override, so let's just keep that as the default.
15 |
16 | * __Install postgres.__ In OSX, use [Homebrew](http://brew.sh/) to install it.
17 |
18 | ```sh
19 | # OSX only
20 | brew install postgres
21 | ```
22 |
23 | * Use [homebrew/services](http://github.com/homebrew/homebrew-services) to start Postgres. Optional but recommended.
24 |
25 | ```sh
26 | # OSX only
27 | brew tap homebrew/services
28 | brew services start postgres
29 | ```
30 |
31 | * __Create a `postgres` user.__ Use PostgreSQL's `createuser` to create a new user. Give it a password `postgres`.
32 |
33 | ```sh
34 | $ createuser --superuser postgres -P
35 | Enter password for new role:
36 | Enter it again:
37 | ```
38 |
39 |
40 |
41 | ## asdf
42 |
43 | > [Asdf](https://github.com/asdf-vm/asdf) is a version manager for everything: Ruby, Elixir, Erlang, Node.js, and so on.
44 |
45 | * __Install asdf__ via git.
46 |
47 | ```sh
48 | git clone https://github.com/asdf-vm/asdf.git ~/.asdf
49 | ```
50 |
51 | * __Add it to bashrc.__ (If you're on zsh, add it to `~/.zshrc`. For fish shell and others, see [asdf setup docs](https://github.com/asdf-vm/asdf#setup)).
52 |
53 | ```sh
54 | # bash / Ubuntu
55 | echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
56 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
57 | ```
58 |
59 | ```sh
60 | # bash / OSX
61 | echo '. $HOME/.asdf/asdf.sh' >> ~/.bash_profile
62 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bash_profile
63 | ```
64 |
65 | ```sh
66 | # Zsh
67 | echo '. $HOME/.asdf/asdf.sh' >> ~/.zshrc
68 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.zshrc
69 | ```
70 |
71 | * __Add plugins__ for Erlang, Elixir and Node.js.
72 |
73 | ```sh
74 | asdf plugin-add erlang https://github.com/asdf-vm/asdf-erlang.git
75 | asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git
76 | asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git
77 | ```
78 |
79 |
80 |
81 | ## Install Erlang/Elixir/Node.js
82 |
83 | * If you have a project with a `.tool-versions`, simply run `asdf install`.
84 |
85 | ```sh
86 | cd my-project
87 | asdf install
88 | ```
89 |
90 | * To configure "global" versions in asdf, create `~/.tool-versions`. Here's a fair starting point.
91 |
92 | ```sh
93 | # These are stable versions as of April 2017.
94 | # To check newer versions, use: `asdf list-all nodejs`
95 | cd ~
96 | echo 'erlang 19.2' >> .tool-versions
97 | echo 'nodejs 6.10.2' >> .tool-versions
98 | echo 'elixir 1.4.2' >> .tool-versions
99 | asdf install
100 | ```
101 |
102 |
103 |
104 | ## Alternatives
105 |
106 | * [Postgres.app](http://postgresapp.com/) is another way to install Postgres.
107 | * [Kiex](https://github.com/taylor/kiex) is an Elixir version manager. It doesn't manage Erlang installations (a dependency of Elixir), however.
108 | * You may also install Erlang and Elixir via Homebrew, though it may be difficult to switch versions later on.
109 |
--------------------------------------------------------------------------------
/practices/rails.md:
--------------------------------------------------------------------------------
1 | # Rails
2 |
3 | In general:
4 |
5 | - Prefer to commit your `config/*.yml` files, except database.yml (_PRIVATE_ _REPOS_ _ONLY!_)
6 | - Make use of special Rails ANNOTATIONS like `TODO`, `FIXME`, and `OPTIMIZE` so rake notes can pick it up.
7 | - Keep README.md updated (always assume a new team member will join anytime)
8 |
9 | CSS and JS:
10 |
11 | - Prefer [sass-rails](https://github.com/rails/sass-rails) as a preprocessor
12 | - Prefer [autoprefixer-rails](https://github.com/ai/autoprefixer-rails) for vendor prefixes
13 | - Prefer [haml](http://haml.info/) for templating (via [hamlit-rails](https://rubygems.org/gems/hamlit-rails))
14 | - Prefer [bootstrap](http://getbootstrap.com) if a CSS framework is needed
15 | - Prefer [bootstrap-sass](https://github.com/twbs/bootstrap-sass) for Bootstrap + Rails integration
16 | - Prefer [rails-assets.org](https://rails-assets.org) for managing 3rd-party JS/CSS
17 | - Prefer [konacha](github.com/jfirebaugh/konacha) for JS unit testing
18 |
19 | Server:
20 |
21 | - Prefer [puma](http://puma.io/) even in development (for multi-threaded support)
22 |
23 | Style Guides:
24 |
25 | - Adhere to [rsjs](https://github.com/rstacruz/rsjs) when writing JS
26 |
27 | Emails:
28 |
29 | - Prefer [letter_opener](https://rubygems.org/gems/letter_opener) for locally testing emails
30 | - Prefer [premailer-rails](https://rubygems.org/gems/premailer-rails) for managing inline email CSS
31 |
32 | Rake tasks:
33 |
34 | - Ensure `db:migrate` runs properly
35 | - Ensure `db:rollback` runs properly
36 | - Ensure `db:seed` runs properly (They get outdated fast!). Alternatively, provide a way to seed a newcomer's project.
37 | - Ensure painless turnovers
38 |
39 | Configuration:
40 |
41 | - Use `config/secrets.yml` to store config
42 | - Use 12-factor style when overrides are needed: `pusher_id: <%= ENV['PUSHER_ID'] || '...' %>`
43 | - Access them in your app via `Rails.application.secrets.pusher_id`
44 |
45 | Avoid:
46 |
47 | - Avoid [less-rails](https://github.com/metaskills/less-rails/). Slow to update, and doesn't support [import globbing](https://github.com/less/less.js/issues/1181)
48 | - Avoid [compass](http://compass-style.org/) unless necessary. Use autoprefixer instead
49 | - Avoid [bootstrap-on-rails](https://github.com/jasontorres/bootstrap-on-rails) because it's .less and not currently maintained
50 | - Avoid [twitter-bootstrap-rails](https://github.com/seyhunak/twitter-bootstrap-rails) because it's .less and has too many abstractions
51 | - Avoid [coffeescript](http://coffeescript.org/). Prefer to use [sprockets-es6](https://rubygems.org/gems/sprockets-es6) instead. ([article](https://robots.thoughtbot.com/replace-coffeescript-with-es6))
52 | - Avoid [bower-rails](https://rubygems.org/gems/bower-rails). Heroku setup can be a pain, and rails-assets is a better choice nowadays.
53 | - Avoid configuration gems like [figaro](http://rubygems.org/gems/figaro), [dotenv](http://rubygems.org/gems/dotenv), etc. Rails 4.1 should render them useless now.
54 | - Avoid [teaspoon](https://github.com/modeset/teaspoon). It has more boilerplate to setup, and doesn't sandbox your test DOM unlike konacha. Use konacha instead
55 | - Avoid [Enums](http://api.rubyonrails.org/v4.1/classes/ActiveRecord/Enum.html). They can cause non-obvious problems with queries ([1](https://hackhands.com/ruby-on-enums-queries-and-rails-4-1/#queries-on-enums), [2](https://bendyworks.com/rails-enum-sharp-knife/), [3](https://github.com/proudcloud/awesome/pull/56#issuecomment-219984596)). Use strings instead.
56 |
57 | ## Also see
58 |
59 | - **[Design practices](design.md#sass)** (covers Sass)
60 | - **[JavaScript practices](javascript.md)** (covers ES6)
61 | - **[Testing practices](testing.md)** (covers Rspec)
62 | - **[Git practices](git.md)** (covers Git and GitHub)
63 |
--------------------------------------------------------------------------------
/workflow/rails-ubuntu1404.md:
--------------------------------------------------------------------------------
1 | # Ubuntu 14.04 Trusty Tahr Setup for RoR Development
2 | ---
3 | ####Installing Ruby
4 | ---
5 | Install Ruby dependencies
6 | ```
7 | sudo apt-get update
8 | sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev
9 | ```
10 | Install Ruby (choose one of the methods below)
11 |
12 | * Rbenv
13 | ```
14 | cd
15 | git clone git://github.com/sstephenson/rbenv.git .rbenv
16 | echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
17 | echo 'eval "$(rbenv init -)"' >> ~/.bashrc
18 | exec $SHELL
19 | git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
20 | echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
21 | exec $SHELL
22 | git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash
23 | rbenv install 2.2.2
24 | rbenv global 2.2.2
25 | ruby -v
26 | ```
27 | * RVM
28 | ```
29 | sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
30 | curl -L https://get.rvm.io | bash -s stable
31 | source ~/.rvm/scripts/rvm
32 | rvm install 2.2.2
33 | rvm use 2.2.2 --default
34 | ruby -v
35 | ```
36 | * Compile from Source
37 | ```
38 | cd
39 | wget http://ftp.ruby-lang.org/pub/ruby/2.2/ruby-2.2.2.tar.gz
40 | tar -xzvf ruby-2.2.2.tar.gz
41 | cd ruby-2.2.2/
42 | ./configure
43 | make
44 | sudo make install
45 | ruby -v
46 | ```
47 | Install bundler
48 | * To skip installation of documentation for each package (Optional)
49 | ```
50 | echo "gem: --no-ri --no-rdoc" >> ~/.gemrc
51 | ```
52 | * Install Bundler
53 | ```
54 | gem install bundler
55 | ```
56 | ---
57 | ####Setting up Git
58 | ---
59 | * Setup initial git configuration
60 | ```
61 | git config --global color.ui true
62 | git config --global user.name "YOUR NAME"
63 | git config --global user.email "YOUR@EMAIL.com"
64 | ```
65 | * Generate SSH key
66 | ```
67 | ssh-keygen -t rsa -C "YOUR@EMAIL.com"
68 | ```
69 | * Or copy from existing; create directory
70 | ```
71 | $ mkdir ~/.ssh
72 | $ cp ~/Downloads/id_rsa ~/.ssh
73 | $ cp ~/Downloads/id_rsa.pub ~/.ssh
74 | ```
75 | * Add key to Github
76 | ```
77 | cat ~/.ssh/id_rsa.pub
78 | ```
79 | * Test git
80 | ```
81 | ssh -T git@github.com
82 | ```
83 | ---
84 | ####Installing Rails
85 | ---
86 | * Install NodeJS
87 | ```
88 | sudo add-apt-repository ppa:chris-lea/node.js
89 | sudo apt-get update
90 | sudo apt-get install nodejs
91 | ```
92 | * Install Rails
93 | ```
94 | gem install rails -v 4.2.1
95 | ```
96 | If you are using rbenv
97 | ```
98 | rbenv rehash
99 | ```
100 | * Check if rails has been installed
101 | ```
102 | rails -v
103 | ```
104 | ---
105 | ####Setting Up MySQL
106 | ---
107 | * Install MySQL
108 | ```
109 | sudo apt-get install mysql-server mysql-client libmysqlclient-dev
110 | ```
111 | ---
112 | ####Setting Up PostgreSQL
113 | ---
114 | * Install PostgreSQL
115 | ```
116 | sudo sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main' > /etc/apt/sources.list.d/pgdg.list"
117 | wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add -
118 | sudo apt-get update
119 | sudo apt-get install postgresql-common
120 | sudo apt-get install postgresql-9.3 libpq-dev
121 | ```
122 |
123 | * Run Postgres
124 | ```
125 | sudo /etc/init.d/postgresql start
126 | ```
127 |
128 | * Setup postgres user
129 | ```
130 | sudo -u postgres createuser mark -s
131 | sudo -u postgres psql
132 | postgres=# \password mark
133 | ```
134 | ---
135 | ####Setting Up MongoDB
136 | ---
137 | * Import MongoDB's public key
138 | ```
139 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
140 | ```
141 | * Create list file for MongoDB
142 | ```
143 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
144 | ```
145 | * Install MongoDB
146 | ```
147 | sudo apt-get update
148 | sudo apt-get install -y mongodb-org
149 | ```
150 | * Start MongoDB
151 | ```
152 | sudo service mongod start
153 | ```
154 |
--------------------------------------------------------------------------------
/practices/qa.md:
--------------------------------------------------------------------------------
1 | ## QA Guidelines
2 |
3 | ###What is Testing?
4 | ####Testing includes the following activities:
5 | * Planning and control.
6 | * Choosing test conditions.
7 | * Designing and executing test cases.
8 | * Checking results.
9 | * Evaluating exit criteria.
10 | * Reporting on the testing process and system under test.
11 | * Finalizing or completing closure activities after a test phase has been completed.
12 | * Reviewing documents (including source code).
13 | * Conducting static analysis.
14 |
15 | ###Why is Testing necessary?
16 |
17 | Humans are fallible. We are prone to errors and we can be affected by time pressure, complex code, complex infrastructure, changing technologies, and/or many system interactions. So testing can have the following objectives:
18 |
19 | 1. Finding defects.
20 | 2. Gaining confidence about the level of quality of the product.
21 | 3. Providing information for decision making.
22 | 4. Preventing defects before the product is released for operational use.
23 |
24 | These objectives can change depending on the viewpoint why testing is done. For Example:
25 |
26 | 1. Development Testing (Component, Integration, System Testing)
27 | * Main objective may be to cause as many failures as possible so that they can be identified and fixed.
28 | 2. Acceptance Testing
29 | * Main objective may be to confirm that system works as expected, to gain the confidence that it has met the requirements.
30 | * In some cases it may be just to assess the quality of the software (with no intention of fixing defects), to give information to stakeholders of the risk of releasing the system at a given time.
31 | 3. Maintenance and Regression Testing.
32 | * This includes testing to ensure that no new defects have been introduced during development of changes.
33 |
34 | ###Seven Testing Principles
35 |
36 | These are general guidelines for testing.
37 |
38 | 1. Testing shows presence of defects
39 | * Testing can show that defects are present, but cannot prove that there are no defects. Testing reduces the probability of undiscovered defects remaining in the software but, even if no defects are found, it is not a proof of correctness.
40 | 2. Exhaustive testing is impossible.
41 | * Testing everything (all combinations of inputs and preconditions) is not feasible except for trivial cases. Instead of exhaustive testing, risk analysis and priorities should be used to focus testing efforts.
42 | 3. Early testing.
43 | * To find defects early, testing activities shall be started as early as possible in the software or system development life cycle, and shall be focused on defined objectives.
44 | 4. Defect clustering.
45 | * Testing effort shall be focused proportionally to the expected and later observed defect density of modules. A small number of modules usually contains most of the defects discovered during pre-release testing, or is responsible for most of the operational failures.
46 | 5. Pesticide paradox.
47 | * If the same tests are repeated over and over again, eventually the same set of test cases will no longer find any new defects. To overcome this “pesticide paradox”, test cases need to be regularly reviewed and revised, and new and different tests need to be written to exercise different parts of the software or system to find potentially more defects.
48 | 6. Testing is context dependent.
49 | * Testing is done differently in different contexts. For example, safety-critical software is tested differently from an e-commerce site.
50 | 7. Absence-of-errors fallacy.
51 | * Finding and fixing defects does not help if the system built is unusable and does not fulfill the user's’ needs and expectations.
52 |
53 | ###Fundamental Test Process
54 |
55 | Test execution is the most visible part of testing. But to be effective and efficient, test plans should include time to be spent on planning the tests, designing test cases, preparing for execution and evaluation of results. The fundamental test process is consisted of the following main activities:
56 |
57 | 1. Test planning and control.
58 | 2. Test analysis and design.
59 | 3. Test implementation and execution.
60 | 4. Evaluating exit criteria and reporting.
61 | 5. Test closure activities.
62 |
63 | Although logically sequential, the activities in the process may overlap or take place concurrently.
64 |
--------------------------------------------------------------------------------
/read/README.md:
--------------------------------------------------------------------------------
1 | # Required reading
2 |
3 | This is a curated listing of all must-read resources for the builders of Proudcloud.
4 |
5 | To add a link, add an item on top (newest first). Feel free to create sections as needed.
6 |
7 | ## Design
8 |
9 | - [Design Machines: How to survive the digital apocalypse](https://louderthanten.com/coax/design-machines)
10 | - [A Book Apart](http://abookapart.com/)
11 | - [100 Things Every Designer Needs to Know About People](http://www.amazon.com/Things-Designer-People-Voices-Matter/dp/0321767535)
12 | - [Web UI Design Best Practices](http://www.uxpin.com/web-ui-design-best-practices.html) by UXPin (free)
13 | - [HTML and CSS: Design and Build Websites](http://www.htmlandcssbook.com/) by Jon Duckett
14 | - [JavaScript and JQuery: Interactive Front-End Web Development ](http://javascriptbook.com/) by Jon Duckett
15 | - [Steal Like An Artist](http://austinkleon.com/steal/) by Austin Kleon
16 | - [Design as Art](http://www.amazon.com/Design-as-Art-Bruno-Munari/dp/0141035811) by Bruno Munari
17 | - [Professional Web Typography](https://prowebtype.com) by Donny Truong
18 | - [Hacker Shelf: Collection of free books for the intellectually curious](http://hackershelf.com/browse/?popular=1)
19 | - [Optical Adjustment](https://medium.com/@lukejonesme/optical-adjustment-b55492a1165c)
20 | - [Free Books for Web Design 2014](http://speckyboy.com/2015/01/12/free-web-design-ebooks-2014/)
21 | - [Photoshop Etiquette](http://www.photoshopetiquette.com/)
22 | - [Facebook Visual Identity](http://officeofbenbarry.com/see/facebook-visual-identity) - insight on branding process
23 | - [How to be a graphic designer without losing your soul](http://www.amazon.com/Graphic-Designer-without-Expanded-Edition/dp/1568989830) by Adrian Shaughnessy
24 | - [rscss: Reasonable System for CSS Stylesheet Structure](https://github.com/rstacruz/rscss)
25 |
26 | #### Repos
27 | - [Web Design Repo](http://www.webdesignrepo.com/)
28 | - [Web Designer Depot](http://www.webdesignerdepot.com/)
29 | - [Unheap](http://www.unheap.com/)
30 | - [Design Leaks](http://designleaks.net/)
31 | - [Psddd](http://psddd.co/)
32 | - [Method & Craft](http://methodandcraft.com/)
33 | - [Makerbook](http://makerbook.net/)
34 |
35 | ## JavaScript
36 |
37 | - [Essential Javascript Links](https://github.com/ericelliott/essential-javascript-links)
38 | - [JavaScript: The Good Parts](http://shop.oreilly.com/product/9780596517748.do)
39 | - [You don't know JavaScript](https://github.com/getify/You-Dont-Know-JS)
40 | - [Things Every Javascript Developer Should Know](http://www.devbattles.com/en/sand/post-1427-Things+Every+Javascript+Developer+Should+Know)
41 | - [Airbnb JavaScript style guide](https://github.com/airbnb/javascript)
42 | - [ES6 Features](git.io/es6features)
43 |
44 | ## Ruby
45 |
46 | - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide)
47 | - [Metaprogramming Ruby](https://pragprog.com/book/ppmetr/metaprogramming-ruby)
48 |
49 | ## Vim
50 |
51 | - [A Byte of Vim](http://www.swaroopch.com/notes/vim/)
52 | - [The Vim Book](http://www.oualline.com/vim-book.html)
53 | - [Learn Vimscript the Hard Way](http://learnvimscriptthehardway.stevelosh.com/)
54 | - [Vim Galore](https://github.com/mhinz/vim-galore)
55 |
56 | ## Coding
57 | - [Pragmatic Programmer](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X)
58 | - [Clean Coder](http://www.amazon.com/The-Clean-Coder-Professional-Programmers/dp/0137081073)
59 | - [Programmers Rantings](http://www.amazon.com/Programmers-Rantings-Programming-Language-Religions-Philosophies-ebook/dp/B00AGXSIXW)
60 |
61 | ## Culture
62 | - [Onboarding](http://blog.mailchimp.com/maintaining-company-culture-through-onboarding/)
63 | - [Team Debt](https://kateheddleston.com/blog/onboarding-and-the-cost-of-team-debt)
64 |
65 | ## Life
66 | - [Personal MBA](http://www.amazon.com/Personal-MBA-Master-Art-Business/dp/1591845572/)
67 | - [Rich Dad, Poor Dad](http://www.amazon.com/Rich-Dad-Poor-Teach-Middle/dp/1612680011/)
68 | - [How to Win Friends and Influence
69 | People](http://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034)
70 |
71 | ## iOS
72 |
73 | - [The iOS Design Guidelines](http://iosdesign.ivomynttinen.com/)
74 | - [iOS Human Interface Guidelines](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/)
75 | - [Swift Style Guide](https://github.com/raywenderlich/swift-style-guide)
76 |
77 | ## Testing
78 | - [Economy of Tests](http://stakeholderwhisperer.com/posts/2015/1/economy-of-tests)
79 |
80 | ## License
81 |
82 | MIT
83 |
84 | Feel free to reuse this list for your own team!
85 |
--------------------------------------------------------------------------------
/practices/i18n.md:
--------------------------------------------------------------------------------
1 | # Rails i18n practices
2 |
3 | Rails gives us [localization features](http://guides.rubyonrails.org/i18n.html) via the rails-i18n gem. While the Rails guide describes the technical details on how to use it, it doesn't prescribe any guidelines on how to name and sort your localization strings. Here's my take on how a project's I18n strings should be sorted out.
4 |
5 | * * * *
6 |
7 | ### Quote your strings
8 | While the YAML format is liberal and quotation marks aren't needed, the consistency is always welcome. It also makes it less ambiguous for non-developers who may edit the YAML file.
9 |
10 | ```coffee
11 | en:
12 | posts:
13 | index:
14 | title: "Blog posts"
15 | description: "These are the latest posts in the blog."
16 | ```
17 |
18 | ### Don't add punctuation
19 | Some strings end in `:`. Don't place them in the YAML file. This will allow for the strings to be reusable later on.
20 |
21 | ```rb
22 | t('.categories') + ":"
23 | ```
24 |
25 | ### Group by controller and action
26 | Place your page's strings under their respective `controller` and `action` names. This allows to you take advantage of Rails's shortcuts. Also, always name your primary title as `title`.
27 |
28 | ```rb
29 | # looks up 'posts.index.title', if you're on the posts#index view
30 | t('.title')
31 | ```
32 |
33 | > See: [lazy lookup](http://guides.rubyonrails.org/i18n.html#lazy-lookup) (guides.rubyonrails.org)
34 |
35 | ### Group strings for partials
36 | The same concept should apply for partials. You can also use the `t('.login')` shortcut inside partial views.
37 |
38 | ```coffee
39 | en:
40 | shared:
41 | nav:
42 | back_to_home: "Back to home"
43 | login: "Log in"
44 | ```
45 |
46 | ### Avoid top-level strings
47 | Don't place strings on the top level such as `t('and')`. Place them on a parent, even an arbitrary one. If you can't think of a parent name, use `common`.
48 |
49 | ```coffee
50 | en:
51 | actions:
52 | submit: "Submit"
53 | add: "Add"
54 | delete: "Delete"
55 | login: "Log in"
56 | common:
57 | or: "or"
58 | and: "and"
59 | ```
60 |
61 | ### Avoid over nesting
62 | Prefer to nest with just one level. Overly-complicated nesting can seem very arbitrary and confusing.
63 |
64 | ```coffee
65 | # Avoid
66 | en:
67 | user:
68 | mail:
69 | status:
70 | delivered: "Delivered"
71 | read: "Read"
72 | ```
73 |
74 | ```coffee
75 | # Better
76 | en:
77 | mail_status:
78 | delivered: "Delivered"
79 | read: "Read"
80 | ```
81 |
82 | ### Familiarize yourself with defaults
83 | The default locale file is available under rails-i18n.
84 |
85 | > See: [locale/en.yml](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml). (svenfuchs/rails-i18n)
86 |
87 |
88 |
89 |
90 | ## Time and date
91 |
92 | ### Don't use .strftime
93 | Use i18n to format timestamps. Define your time formats in `time.formats`. Listed below are the default time formats available in Rails.
94 |
95 | ```rb
96 | l(Time.now, format: :short)
97 | ```
98 |
99 | ```coffee
100 | en:
101 | time:
102 | formats:
103 | default: "%a, %d %b %Y %H:%M:%S %z"
104 | short: "%d %b %H:%M"
105 | ```
106 |
107 | ### Same with dates
108 | The `I18n.l` method also supports dates. Also, when creating new formats, add comments on what they should look like to help your teammates along.
109 |
110 | ```rb
111 | l(Date.today, format: :long)
112 | ```
113 |
114 | ```yml
115 | en:
116 | date:
117 | formats:
118 | default: "%Y-%m-%d" # 2015-06-25
119 | long: "%B %d, %Y" # June 25, 2015
120 | short: "%b %d" # Jun 25
121 | ```
122 |
123 | > See: [Adding date time formats](http://guides.rubyonrails.org/i18n.html#adding-date-time-formats) (guides.rubyonrails.org)
124 |
125 |
126 |
127 | ## Forms
128 |
129 | ### Use ActiveRecord errors
130 | The Rails method [full_messages](http://devdocs.io/rails/activemodel/errors#method-i-full_messages) looks up in predefined locations in your locale file. Take advantage of them. See [the cheatsheet](http://ricostacruz.com/cheatsheets/rails-i18n.html) for more.
131 |
132 | ```rb
133 | person = Person.create
134 | person.errors.full_messages
135 | #=> ["Name is too short (minimum is 5 characters)",
136 | # "Name can't be blank", "Email can't be blank"]
137 | ```
138 |
139 | ```
140 | activerecord.errors.models.[model_name].attributes.[attribute_name].[error]
141 | activerecord.errors.models.[model_name].[error]
142 | activerecord.errors.messages.[error]
143 | errors.attributes.[attribute_name].[error]
144 | errors.messages.[error]
145 | ```
146 |
147 | > See: [Translations for the error_messages_for helper](http://guides.rubyonrails.org/i18n.html#translations-for-the-active-record-error-messages-for-helper) (guides.rubyonrails.org)
148 |
149 | ### Use form labels
150 | There are also conventions on where [f.label](http://devdocs.io/rails/actionview/helpers/formbuilder#method-i-label) will look up labels.
151 |
152 | ```rb
153 | form_for @post do
154 | f.label :body
155 | ```
156 |
157 | ```coffee
158 | helpers:
159 | # helpers.label..
160 | label:
161 | post:
162 | body: "Your body text"
163 | ```
164 |
--------------------------------------------------------------------------------
/workflow/ios.md:
--------------------------------------------------------------------------------
1 | # iOS Development Workflow
2 |
3 | ## Setting up a new project
4 |
5 | 1. Create a new project
6 |
7 | 1. __File__ -> __New__ -> __Project__ or press `SHIFT + ⌘ + N` to create a new project.
8 |
9 | 2. Choose __Single View Application__ then click Next.
10 |
11 | 3. Type the __Name__ of your project.
12 |
13 | 4. Type your __Organization Name__.
14 |
15 | 5. Type your __Organization Identifier__. The naming convention for __Organization Identifier__ is reverse domain naming style (e.g. `net.proudcloud.ios.NowShowing`). The platform is included so we can also use this naming convention for Android ports of our apps, in this case `net.proudcloud.android.NowShowing`.
16 |
17 | 6. Choose __Swift__ as the Language
18 |
19 | 7. Choose the __Devices__ to support. Usually, it is just iPhone. Universal is selected when we need to support iPad.
20 |
21 | 2. Set up Build Number auto-updates
22 |
23 | 1. Click on your project workspace. It is the row with the little blue file icon with your project's name, targets, and SDK version.
24 |
25 | 2. Go to __Targets__ -> __Project Name__.
26 |
27 | 3. Then in the __General__ panel, change the default __Version__ of the app to `0.0.1`.
28 |
29 | 4. Then go to __Build Phases__.
30 |
31 | 5. Add a new phase by clicking the `+` on the upper left corner of the panel then click __New Run Script Phase__.
32 |
33 | 6. Collapse the newly added phase and paste the following:
34 | ```
35 | buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
36 | buildNumber=$(($buildNumber + 1))
37 | /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
38 | ```
39 | 7. Rename this phase to __Auto-update Build Number__ by double-clicking __Run Script__
40 |
41 | 8. Then drag this new phase above __Copy Bundle Resources__ so that our build number is updated before `Info.plist` is copied to our archive. This ensures that the new archive has the updated build number.
42 |
43 |
44 | 3. Update the project structure
45 |
46 | Make sure you have the following project structure:
47 | ```
48 | ProjectName
49 | `- API
50 | `- Models
51 | `- Views
52 | `- Controllers
53 | `- Extensions
54 | AppDelegate.swift
55 | Images.xcassets
56 | Main.storyboard
57 | LaunchScreen.xib
58 | Supporting Files
59 | `- Info.plist
60 | `- BridgingHeader.h
61 | ```
62 |
63 |
64 | 4. Check-in your project to GitHub
65 |
66 | 1. Initialize the project:
67 | ```
68 | $ git init
69 | ```
70 |
71 | 2. Commit your changes:
72 | ```
73 | $ git add --all
74 | ```
75 |
76 | 3. Set up the remote:
77 | ```
78 | $ git remote add origin
79 | ```
80 |
81 | 4. Push your changes
82 | ```
83 | $ git push -u origin master
84 | ```
85 |
86 |
87 | ## Setting up CocoaPods
88 |
89 | 1. Go to your project's directory
90 | ```
91 | $ cd
92 | ```
93 |
94 | 2. Create a new file named `Gemfile`.
95 | ```
96 | $ touch Gemfile && vim Gemfile
97 | ```
98 |
99 | 3. Add the following to your Gemfile:
100 |
101 | ```
102 | source 'https://rubygems.org'
103 |
104 | gem 'cocoapods'
105 | ```
106 |
107 | 4. Save and exit by typing `:wq`
108 |
109 | 5. Install CocoaPods by running:
110 | ```
111 | $ bundle install
112 | ```
113 |
114 | 6. When Bundler finishes installing CocoaPods, run:
115 |
116 | ```
117 | $ pod init
118 | ```
119 |
120 | This will create new file named __Podfile__ in your project directory. You can now add Pods in this file then run `pod install` to install them.
121 |
122 |
123 | ## Versioning
124 |
125 | We'll follow the guidelines below as our versioning system.
126 |
127 | Given we have the `x.y.z` as our version:
128 |
129 | - We increment `z` when we publish bug fixes, and really small updates like changing a text.
130 | - We increment `y` when we publish minor features that don't really affect the usage of the app.
131 | - We increment `x` when we publish really big updates (e.g. major UI overhaul, breaking changes, etc.)
132 |
133 | TLDR; `..`
134 |
135 | Also take note of our __Build Number__. The build number denotes how many times we've built the app by running (`⌘ + R`) or building the app (`⌘ + B`).
136 |
137 | __NOTE:__ In cases where you have conflicts in the build number, always choose the higher build number.
138 |
139 | ## Branching
140 |
141 | *TBA*
142 |
143 | ## Deployment
144 |
145 | Follow the following steps to submit a build to the App Store.
146 |
147 | 1. Make sure __iOS Device__ is selected as your __Destination__. This should be similar to selecting your device to run your app on.
148 | 2. On Xcode's menu bar, Click __Product__ -> __Archive__. When this finishes, Xcode should automatically open the __Organizer__ window.
149 | 3. Click on the latest archive that you created, and click __Validate__. This validates your __*.ipa file__ (iOS application archive) for App Store submission.
150 | - (Optional) Fix errors in your build, if any.
151 | 4. If there are no errors in your build, click __Submit to App Store__ to submit your app. Additional checks will be done to your app and if it passes, your app is now uploaded to the App Store.
152 | 5. Login to __iTunes Connect__ to continue your submission.
153 | 6. Complete the app details, screenshots, and all required information to be able to submit.
154 | 7. Choose a build to submit.
155 | 8. (Optional) You may choose to publish your app manually or automatically, when your app passes the review process or manually publish
156 | 9. Click __Submit for Review__ and pray that your app passes the review process.
157 |
158 | Your app should now say that it's __Waiting for Review__. This usually takes 1 to 2 weeks, and it's up to Apple now whether your app passes or gets rejected.
159 |
160 |
161 | ## Post-Deployment
162 |
163 | After publishing your app, make sure you create a release tag for the new version you published.
164 |
165 | For example, we've just published `v1.2.8` on the App Store
166 |
167 | ```
168 | $ git tag v1.2.8
169 | ```
170 |
171 | Then edit this release tag on GitHub and add the changes made in this build.
172 |
--------------------------------------------------------------------------------
/practices/testing.md:
--------------------------------------------------------------------------------
1 | # General Philosophy
2 |
3 | - Test the **app**, not the **framework** or **library**.
4 |
5 | - **TDD** is not required, tested code is.
6 |
7 | - Code coverage doesn't mean anything. You can never know all the edge cases.
8 |
9 | - Code should be easy to test. If it's hard to test, change your code.
10 |
11 | - Fast tests are happy tests.
12 |
13 |
14 | # RSpec
15 |
16 | - The `should` syntax is [dead](https://github.com/rspec/rspec-expectations/blob/master/Should.md#why-switch-over-from-should-to-expect). Use the `expect` syntax. This also means no `shoulda`.
17 |
18 | ```ruby
19 | # ✗ Avoid
20 | user.name.should eq "Davy Jones"
21 |
22 | # ✓ OK
23 | expect(user.name).to eq "Davy Jones"
24 | ```
25 |
26 | - You can run specific examples by providing their line number when you run your tests.
27 |
28 | ```
29 | > rspec spec/models/user_spec.rb:11
30 | ```
31 |
32 | - Prefer to run specs with the `--color` or `-c` and the `--format=doc` or `-f d` options. Or store it in an `.rspec` file.
33 |
34 | ```
35 | # .rspec
36 | --color
37 | --format=doc
38 | ```
39 |
40 | - Running specs with the `--profile` or `-p` option will display the top ten slowest examples. It also accepts a number argument. Run this in your CI, but don't place it in `.rspec`.
41 |
42 | ```
43 | # Displays the 5 slowest examples
44 | > rspec spec/models/user_spec.rb -p 5
45 | ```
46 |
47 | - Add `.rspec-local` to your project's `.gitignore` file. This will allow individual developers to customize their own default rspec parameters.
48 |
49 | ```sh
50 | echo .rspec-local >> .gitignore
51 | ```
52 |
53 | - Use [shared_examples](https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples) when possible.
54 |
55 | ## `describe`
56 |
57 | - Consider examples as the project's documentation.
58 |
59 | - Describe your methods properly and accurately. If you change what the code does, do **NOT** forget to update the test's description.
60 |
61 | - Use double quotes for the description string.
62 |
63 | - Your top level `describe` block should indicate the class under test.
64 |
65 | ```ruby
66 | # This is actually a smoke test
67 | describe Venue do
68 | ...
69 | end
70 | ```
71 |
72 | - No instance varaibles. Use `let` or `let!`. If in doubt, use `let!`.
73 |
74 | - `before`, `around`, `after` and `let` blocks should come right after a `describe` block and before the next `describe` or `context` block.
75 |
76 | - Prefix your methods with `#` if it's an instance method and `.` if it's a class method or model scope.
77 |
78 | ```ruby
79 | describe "#instance_method"
80 | describe ".class_method"
81 | ```
82 |
83 | ## `context`
84 |
85 | - Use `context` for branching code. Prefer using `with` and `without` or `when`.
86 |
87 | ```ruby
88 | describe "#has_comments?" do
89 | context "in a post with comments" do
90 | let!(:comment) { create :comment, post: post }
91 | it "returns true" do
92 | expect(post.has_comments?).to eq true
93 | end
94 | end
95 |
96 | context "in a post without comments" do
97 | it "returns false" do
98 | expect(post.has_comments?).to eq false
99 | end
100 | end
101 | ```
102 |
103 | ## `it`
104 |
105 | - Prefer one expectation per `it` block.
106 |
107 | - Be explicit with your descriptions. Say what the code *does*, not what it *should* do. (aka: don't start descriptions with "should")
108 |
109 | ```ruby
110 | # ✓ OK
111 | it "returns true"
112 | it "sends the email"
113 |
114 | # ✗ Avoid
115 | it "should be true"
116 | it "should send the email"
117 | ```
118 |
119 | - Prefer `eq` over `be` and magic matchers.
120 |
121 | ```ruby
122 | # ✓ OK
123 | expect(user.admin?).to eq true
124 | expect(user.age).to eq 12
125 |
126 | # ✗ Avoid
127 | expect(user).to be_admin
128 | expect(user.age).to be 12
129 | ```
130 |
131 | - Prefer multiline blocks over one liners.
132 |
133 | - If you must use one liners, use `is_expected`. Again, no `shoulda`.
134 |
135 |
136 | ## `pending`
137 |
138 | - Mark incomplete tests with `pending`.
139 |
140 | ```ruby
141 | it "publishes the event" do
142 | pending "because reasons"
143 | event.publish!
144 | expect(event.published?).to eq true
145 | end
146 | ```
147 |
148 | - For methods that don't have tests yet (but should), use an `it` with no block. Don't use `pending`.
149 |
150 | ```ruby
151 | # ✗ Avoid
152 | describe "#untested_method" do
153 | pending "because reasons"
154 | end
155 |
156 | # ✓ OK
157 | it "#untested_method"
158 |
159 | # ❤ BETTER
160 | describe "#untested_method" do
161 | it "succeeds with valid data"
162 | it "returns nil when given invalid options"
163 | end
164 | ```
165 |
166 | ## Metaprogramming Tests
167 |
168 | - Don't.
169 |
170 | # Rails
171 |
172 | - Follow the `rspec-rails` [directory structure](https://relishapp.com/rspec/rspec-rails/docs/directory-structure) and naming conventions.
173 |
174 | - `cucumber` can be cucumbersome. Use RSpec `features` specs with [capybara](https://github.com/jnicklas/capybara) instead.
175 |
176 | - Delegate routing and view specs to `features` specs.
177 |
178 | - Only write controller specs for actions that cannot be covered by `features` specs. Otherwise, write `features` specs.
179 |
180 | - Use [`requests` or `api` specs](https://github.com/rspec/rspec-rails#request-specs) for testing API requests.
181 |
182 | - Do not forget to test helpers and rake tasks.
183 |
184 | - Prefer `spec_helper` over `rails_helper`. Only require `rails_helper` for tests that need Rails to work.
185 |
186 | - Always include the [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner) gem or it's faster cousin, [database_rewinder](https://github.com/amatsuda/database_rewinder).
187 |
188 | - Use [factory_girl_rails](https://github.com/thoughtbot/factory_girl_rails) over fixtures.
189 |
190 | - In your `rails_helper`, always set `config.use_transactional_fixtures` to `false`. This isn't necessary if you're using database_rewinder.
191 |
192 | - External HTTP requests are slow. Always mock them or use gems like [vcr](https://github.com/vcr/vcr) and [WebMock](https://github.com/bblimke/webmock).
193 |
194 | - When mocking/stubbing, never mock/stub the unit you are testing.
195 |
196 | ```ruby
197 | # ✗ Avoid
198 | allow(User).to receive(:count).and_return(2)
199 | expect(User.count).to eq 2
200 | ```
201 |
202 |
203 | ## Model specs
204 |
205 | - No mocking. Test the actual models.
206 |
207 | - Skip association tests.
208 |
209 | - Test validations. Presence validation specs are optional.
210 | ```ruby
211 | # Validations
212 | expect(valid_project.errors.full_messages).to eq []
213 | expect(invalid_project.errors.full_messages).to include "Video url is not a valid Youtube/Vimeo url"
214 | ```
215 |
216 | - Test scopes for both inclusion and exclusion.
217 | ```ruby
218 | # Scopes
219 | expect(Project.published).to include published_project
220 | expect(Project.published).to_not include unpublished_project
221 | ```
222 |
223 | - Callbacks testing can be done in a couple of ways.
224 | ```ruby
225 | # Assumes an `#ensure_default_role` callback that sets the default role if not provided
226 |
227 | # You can use a proc
228 | user.role = nil
229 | expect { user.save }.to change(user, :role).to("default")
230 |
231 | # or test the effect
232 | user.role = "admin"
233 | user.save
234 | expect(user.reload.role).to eq "admin"
235 |
236 | # or test for the just the call
237 | expect_any_instance_of(User).to receive(:ensure_default_role)
238 | user.save
239 |
240 | # then test the functionality
241 | user.nil
242 | user.send :ensure_default_role
243 | expect(user.role).to eq "default"
244 | ```
245 |
246 | - Testing `private` methods can be optional, but only if there is a public method spec that covers it.
247 |
248 |
249 | ## View specs
250 |
251 | Don't. Prefer to use this time to write feature specs instead.
252 |
253 |
254 | ## Controller specs
255 |
256 | - See [Features](#feature-specs).
257 |
258 |
259 | ## Lib specs
260 |
261 | - Unless you autoloaded the file you're testing, you will need to `require` it.
262 |
263 | - Do not require `rails_helper` if you can avoid it. Mock what you can.
264 |
265 |
266 | ## Helper specs
267 |
268 | - RSpec provides a `helper` object so you don't have to include the module in a dummy class to test it.
269 | ```ruby
270 | expect(helper.image_url_for user).to eq "http://wat.com/img/fifi"
271 | ```
272 |
273 |
274 | ## Mailer specs
275 |
276 | - Always mock the models.
277 |
278 | - Do not test `#deliver`.
279 |
280 | - Test for addresses, subject and attachments.
281 | ```ruby
282 | expect(mailer.to).to eq recipient.email
283 | expect(mailer.from).to eq sender.email
284 | expect(mailer.reply_to).to eq sender.reply_to_email
285 | expect(mailer.attachments.size).to eq 1
286 | ```
287 |
288 |
289 | ## Request specs
290 |
291 | - Request specs are considered as integration tests. Treat them as such.
292 |
293 | - Only use these specs for testing APIs. Use [Features](#feature-specs) for pages.
294 |
295 | - Test the body and status in the same example.
296 | ```ruby
297 | it "returns the correct user" do
298 | get user_path(user)
299 | expect(response.body["id"]).to eq user.id
300 | expect(response.status).to eq 200
301 | end
302 | ```
303 |
304 | - Use helpers to reduce duplication. For example, assuming you're working on a JSON API, this helper will clean up the parsing logic for you.
305 | ```ruby
306 | # support/api_helpers.rb
307 | module ApiHelpers
308 | def json
309 | JSON.parse(response.body)
310 | end
311 | end
312 |
313 | # rails_helper.rb
314 | config.include ApiHelpers, type: :request
315 |
316 | # usage
317 | expect(json["id"]).to eq user.id
318 | ```
319 |
320 |
321 | ## Feature Specs
322 |
323 | - Use `feature` and `scenario` blocks.
324 |
325 | ```ruby
326 | feature "User Authentication" do
327 | scenario "with valid credentials" do
328 | ...
329 | end
330 | end
331 | ```
332 |
333 | - Prefer to test for element visibility instead of testing model effects when possible.
334 |
335 | ```ruby
336 | expect(page).to have_link "Log Out"
337 |
338 | # ✗ Avoid
339 | expect(user.signed_in?).to eq true # This should be in a unit test
340 | ```
341 |
342 | - Try to be more selective of tests. Using `expect(page).to have_content` will lead to really long error messages.
343 | ```ruby
344 | # ✗ Avoid
345 | expect(page).to have_content "Log Out"
346 |
347 | # ✓ OK
348 | expect(page).to have_selector '#nav', text: /Log Out/
349 |
350 | # ❤ BETTER, if it works
351 | within '#nav' do
352 | expect(page).to have_content "Log Out"
353 | end
354 | ```
355 | - Multiple expectations per `scenario` is encouraged. Each scenario takes time to spin up, so using less scenarios means faster tests.
356 |
357 | - Helper methods inside `feature` blocks or within the spec file is allowed.
358 |
359 | - Limit the usage of the `js: true` tag only to blocks that have javascript interaction.
360 |
361 | - Use [konacha](https://github.com/jfirebaugh/konacha) for unit javascript testing.
362 |
363 | - Prefer [poltergeist](https://github.com/teampoltergeist/poltergeist) over the default javascript driver, `selenium`. Avoid [capybara-webkit](https://github.com/thoughtbot/capybara-webkit).
364 |
365 | - There will be cases where you will be needing `selenium` to see what's going on. This snippet provides you with a `selenium: true` tag.
366 |
367 | ```ruby
368 | # rails_helper.rb
369 | Capybara.javascript_driver = :poltergeist
370 |
371 | config.before(:each) do |example|
372 | Capybara.current_driver = :selenium if example.metadata[:selenium]
373 | end
374 | ```
375 |
376 | - Don't use `sleep` in your specs. If you feel like you really need to, ask first.
377 |
378 | - Use `find_button('Save').trigger('click')` instead of `click_button('Save')` for javascript enabled specs.
379 |
380 | ## Factories
381 |
382 | - Always include the syntax helpers in your tests. This makes `build` and `create` available in your test cases.
383 |
384 | ```ruby
385 | # rails_helper.rb
386 | config.include FactoryGirl::Syntax::Methods
387 | ```
388 |
389 | - Prefer `build` over `create`, if you can get away with it. This can lead to faster tests.
390 |
391 | - Avoid `build_stubbed`.
392 |
393 | - Never hard-code emails and similar fields that must be unique. Use `sequence`.
394 |
395 | ```ruby
396 | factory :user do
397 | sequence(:email) { |i| "user-#{i}@email.com" }
398 | ...
399 | end
400 | ```
401 |
402 | - Place reusable sequences in a separate file.
403 |
404 | ```ruby
405 | # spec/factories/factory_sequences.rb
406 | FactoryGirl.define do
407 | sequence(:uid) { |i| SecureRandom.uuid }
408 | sequence(:email) { |i| "user-#{i}@email.com" }
409 | end
410 |
411 | factory :admin do
412 | uid
413 | email
414 | end
415 |
416 | factory :client do
417 | uid
418 | email
419 | end
420 | ```
421 |
422 | - [Traits](https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#traits) can be used to remove duplication. But use them sparingly.
423 |
424 | - Make sure that factories are always up to date.
425 |
426 | - Always provide the simplest defaults for your factories. Prefer to only add fields that are validated such that records built through the factory will pass validation. Other fields would only serve to make for confusing future tests and make it difficult to test default behavior.
427 |
428 | ```ruby
429 | class Profile < ActiveRecord::Base
430 | validates :name, presence: true
431 | validates :gender, inclusion: %w(male female)
432 | end
433 |
434 | factory :profile do
435 | name "Jack Sparrow"
436 | gender "male"
437 | occupation "Pirate" # <- Don't
438 | bio "Jack is a pirate lord of the seven seas." # <- Don't
439 | end
440 | ```
441 |
442 | - Test your factories. This will make it easy to spot any factories that may be out of date.
443 |
444 | ```ruby
445 | EXCLUDED = [:factories, :to, :exclude, :if, :any]
446 |
447 | FactoryGirl.factories.map(&:name).each do |factory_name|
448 | next if EXCLUDED.include?(factory_name)
449 |
450 | it "the #{factory_name} factory is valid" do
451 | expect(build factory_name).to be_valid
452 | end
453 | end
454 | ```
455 |
--------------------------------------------------------------------------------