|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+============
|
|
|
2
|
+Contributing
|
|
|
3
|
+============
|
|
|
4
|
+
|
|
|
5
|
+Some ground rules:
|
|
|
6
|
+
|
|
|
7
|
+* To avoid disappointment, new features should be discussed on the mailing list
|
|
|
8
|
+ (django-oscar@googlegroups.com) before serious work starts.
|
|
|
9
|
+
|
|
|
10
|
+* Write tests! Pull requests will be rejected if sufficient tests aren't
|
|
|
11
|
+ provided. See the guidance below on the testing conventions that oscar uses
|
|
|
12
|
+
|
|
|
13
|
+* Write docs! Please update the documentation when altering behaviour or introducing new features.
|
|
|
14
|
+
|
|
|
15
|
+* Write good commit messages: see `Tim Pope's excellent note`_.
|
|
|
16
|
+
|
|
|
17
|
+.. _`Tim Pope's excellent note`: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
|
|
18
|
+
|
|
|
19
|
+* Make pull requests against Oscar's master branch unless instructed otherwise.
|
|
|
20
|
+
|
|
|
21
|
+Installation
|
|
|
22
|
+============
|
|
|
23
|
+
|
|
|
24
|
+After forking, run::
|
|
|
25
|
+
|
|
|
26
|
+ git clone git@github.com:<username>/django-oscar.git
|
|
|
27
|
+ cd django-oscar
|
|
|
28
|
+ mkvirtualenv oscar # optional but recommended
|
|
|
29
|
+ make install
|
|
|
30
|
+
|
|
|
31
|
+Running tests
|
|
|
32
|
+=============
|
|
|
33
|
+
|
|
|
34
|
+Oscar uses a nose_ testrunner which can be invoked using::
|
|
|
35
|
+
|
|
|
36
|
+ ./runtests.py
|
|
|
37
|
+
|
|
|
38
|
+.. _nose: http://nose.readthedocs.org/en/latest/
|
|
|
39
|
+
|
|
|
40
|
+To run a subset of tests, you can use filesystem or module paths. These two
|
|
|
41
|
+commands will run the same set of tests::
|
|
|
42
|
+
|
|
|
43
|
+ ./runtests.py tests/unit/order
|
|
|
44
|
+ ./runtests.py tests.unit.order
|
|
|
45
|
+
|
|
|
46
|
+To run an individual test class use one of::
|
|
|
47
|
+
|
|
|
48
|
+ ./runtests.py tests/unit/order:TestSuccessfulOrderCreation
|
|
|
49
|
+ ./runtests.py tests.unit.order:TestSuccessfulOrderCreation
|
|
|
50
|
+
|
|
|
51
|
+(Note the ':'.)
|
|
|
52
|
+
|
|
|
53
|
+To run an individual test, use one of::
|
|
|
54
|
+
|
|
|
55
|
+ ./runtests.py tests/unit/order:TestSuccessfulOrderCreation.test_creates_order_and_line_models
|
|
|
56
|
+ ./runtests.py tests.unit.order:TestSuccessfulOrderCreation.test_creates_order_and_line_models
|
|
|
57
|
+
|
|
|
58
|
+Oscar's testrunner uses the progressive_ plugin when running all tests, but uses
|
|
|
59
|
+the spec_ plugin when running a subset. It is a good practice to name your test
|
|
|
60
|
+cases and methods so that the spec output reads well. For example::
|
|
|
61
|
+
|
|
|
62
|
+ $ ./runtests.py tests/unit/offer/benefit_tests.py:TestAbsoluteDiscount
|
|
|
63
|
+ nosetests --verbosity 1 tests/unit/offer/benefit_tests.py:TestAbsoluteDiscount -s -x --with-spec
|
|
|
64
|
+ Creating test database for alias 'default'...
|
|
|
65
|
+
|
|
|
66
|
+ Absolute discount
|
|
|
67
|
+ - consumes all lines for multi item basket cheaper than threshold
|
|
|
68
|
+ - consumes all products for heterogeneous basket
|
|
|
69
|
+ - consumes correct quantity for multi item basket more expensive than threshold
|
|
|
70
|
+ - correctly discounts line
|
|
|
71
|
+ - discount is applied to lines
|
|
|
72
|
+ - gives correct discount for multi item basket cheaper than threshold
|
|
|
73
|
+ - gives correct discount for multi item basket more expensive than threshold
|
|
|
74
|
+ - gives correct discount for multi item basket with max affected items set
|
|
|
75
|
+ - gives correct discount for single item basket cheaper than threshold
|
|
|
76
|
+ - gives correct discount for single item basket equal to threshold
|
|
|
77
|
+ - gives correct discount for single item basket more expensive than threshold
|
|
|
78
|
+ - gives correct discounts when applied multiple times
|
|
|
79
|
+ - gives correct discounts when applied multiple times with condition
|
|
|
80
|
+ - gives no discount for a non discountable product
|
|
|
81
|
+ - gives no discount for an empty basket
|
|
|
82
|
+
|
|
|
83
|
+ ----------------------------------------------------------------------
|
|
|
84
|
+ Ran 15 tests in 0.295s
|
|
|
85
|
+
|
|
|
86
|
+.. _progressive: http://pypi.python.org/pypi/nose-progressive/
|
|
|
87
|
+.. _spec: http://darcs.idyll.org/~t/projects/pinocchio/doc/#spec-generate-test-description-from-test-class-method-names
|
|
|
88
|
+
|
|
|
89
|
+Playing in the sandbox
|
|
|
90
|
+======================
|
|
|
91
|
+
|
|
|
92
|
+Oscar ships with a 'sandbox' site which can be run locally to play around with
|
|
|
93
|
+Oscar using a browser. Set it up by::
|
|
|
94
|
+
|
|
|
95
|
+ make sandbox
|
|
|
96
|
+ cd sites/sandbox
|
|
|
97
|
+ ./manage.py runserver
|
|
|
98
|
+
|
|
|
99
|
+This will create the database and load some fixtures for categories and shipping
|
|
|
100
|
+countries.
|
|
|
101
|
+
|
|
|
102
|
+Writing docs
|
|
|
103
|
+============
|
|
|
104
|
+
|
|
|
105
|
+There's a helper script for building the docs locally::
|
|
|
106
|
+
|
|
|
107
|
+ cd docs
|
|
|
108
|
+ ./test_docs.sh
|
|
|
109
|
+
|
|
|
110
|
+Conventions
|
|
|
111
|
+===========
|
|
|
112
|
+
|
|
|
113
|
+General
|
|
|
114
|
+-------
|
|
|
115
|
+
|
|
|
116
|
+* PEP8 everywhere while remaining sensible
|
|
|
117
|
+
|
|
|
118
|
+URLs
|
|
|
119
|
+----
|
|
|
120
|
+
|
|
|
121
|
+* List pages should use plurals, eg ``/products/``, ``/notifications/``
|
|
|
122
|
+
|
|
|
123
|
+* Detail pages should simply be a PK/slug on top of the list page, eg
|
|
|
124
|
+ ``/products/the-bible/``, ``/notifications/1/``
|
|
|
125
|
+
|
|
|
126
|
+* Create pages should have 'create' as the final path segment, eg
|
|
|
127
|
+ ``/dashboard/notifications/create/``
|
|
|
128
|
+
|
|
|
129
|
+* Update pages are sometimes the same as detail pages (ie when in the
|
|
|
130
|
+ dashboard). In those cases, just use the detail convention, eg
|
|
|
131
|
+ ``/dashboard/notifications/3/``. If there is a distinction between the detail
|
|
|
132
|
+ page and the update page, use ``/dashboard/notifications/3/update/``.
|
|
|
133
|
+
|
|
|
134
|
+* Delete pages, eg ``/dashboard/notifications/3/delete/``
|
|
|
135
|
+
|
|
|
136
|
+View class names
|
|
|
137
|
+----------------
|
|
|
138
|
+
|
|
|
139
|
+Classes should be named according to::
|
|
|
140
|
+
|
|
|
141
|
+ '%s%sView' % (class_name, verb)
|
|
|
142
|
+
|
|
|
143
|
+For example, ``ProductUpdateView``, ``OfferCreateView`` and
|
|
|
144
|
+``PromotionDeleteView``. This doesn't fit all situations but it's a good basis.
|