---
title: "Menulis dan menjalankan percobaan"
version: 5.2
locale: id
source: https://docs.djangoproject.com/id/5.2/topics/testing/overview/
canonical: https://djangodocs.dev/id/5.2/topics/testing/overview/
---
# Menulis dan menjalankan percobaan

> **See also**
>
> [testing tutorial](/id/5.2/intro/tutorial05/), the [testing tools reference](/id/5.2/topics/testing/tools/), dan [advanced testing topics](/id/5.2/topics/testing/advanced/).

Dokumen ini dipisah menjadi dua bagian utama. Pertama, kami menjelaskan bagaimana menulis percobaan dengan Django. Kemudian, kami menjelaskan bagaimana menjalankan mereka.

## Menulis percobaan

Django's unit tests use a Python standard library module: [`unittest`](https://docs.python.org/3/library/unittest.html#module-unittest). This
module defines tests using a class-based approach.

Here is an example which subclasses from [`django.test.TestCase`](/id/5.2/topics/testing/tools/#django.test.TestCase),
which is a subclass of [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase) that runs each test inside a
transaction to provide isolation:

```
from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
    def setUp(self):
        Animal.objects.create(name="lion", sound="roar")
        Animal.objects.create(name="cat", sound="meow")

    def test_animals_can_speak(self):
        """Animals that can speak are correctly identified"""
        lion = Animal.objects.get(name="lion")
        cat = Animal.objects.get(name="cat")
        self.assertEqual(lion.speak(), 'The lion says "roar"')
        self.assertEqual(cat.speak(), 'The cat says "meow"')
```

When you [run your tests](#running-tests), the default behavior of the
test utility is to find all the test case classes (that is, subclasses of
[`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase)) in any file whose name begins with `test`,
automatically build a test suite out of those test case classes, and run that
suite.

Untuk lebih rinci tentang [`unittest`](https://docs.python.org/3/library/unittest.html#module-unittest), lihat dokumentasi Python.

> **Dimana seharusnya percobaan berada?**
>
> Cetakan awalan [`startapp`](/id/5.2/ref/django-admin/#django-admin-startapp) membuat file `tests.py` di aplikasi baru. Ini mungkin baik-baik saja jika anda hanya memiliki beberapa pengujian, tetapi saat rangkaian pengujian anda berkembang, anda mungkin ingin menyusunnya kembali menjadi paket pengujian sehingga anda dapat membagi pengujian anda menjadi submodul yang berbeda seperti `test_models.py`, \` test\_views.py\`, `test_forms.py`, dll. Silakan pilih skema organisasi apa pun yang anda suka.
>
> Lihat juga [Menggunakan penjalan percobaan Django untuk menjalankan aplikasi digunakan kembali](/id/5.2/topics/testing/advanced/#testing-reusable-applications).

> **Warning**
>
> If your tests rely on database access such as creating or querying models,
> be sure to create your test classes as subclasses of
> [`django.test.TestCase`](/id/5.2/topics/testing/tools/#django.test.TestCase) rather than [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase).
>
> Using [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase) avoids the cost of running each test in a
> transaction and flushing the database, but if your tests interact with
> the database their behavior will vary based on the order that the test
> runner executes them. This can lead to unit tests that pass when run in
> isolation but fail when run in a suite.

## Menjalankan percobaan

Setelah anda menulis pengujian, jalankan dengan menggunakan perintah [`test`](/id/5.2/ref/django-admin/#django-admin-test) dari utilitas `manage.py` proyek anda:

```shell
$ ./manage.py test
```

Test discovery is based on the unittest module's [built-in test
discovery](https://docs.python.org/3/library/unittest.html#unittest-test-discovery).  By default, this will discover tests in
any file named `test*.py` under the current working directory.

Anda dapat menentukan pengujian tertentu untuk dijalankan dengan menyediakan sejumlah "label pengujian" ke `./manage.py test`. Setiap label pengujian bisa berupa jalur bertitik penuh Python ke paket, modul, subkelas `TestCase`, atau metode pengujian. Contohnya:

```shell
# Run all the tests in the animals.tests module
$ ./manage.py test animals.tests

# Run all the tests found within the 'animals' package
$ ./manage.py test animals

# Run just one test case class
$ ./manage.py test animals.tests.AnimalTestCase

# Run just one test method
$ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak
```

You can also provide a path to a directory to discover tests below that
directory:

```shell
$ ./manage.py test animals/
```

Anda dapat menentukan kecocokan pola nama berkas penyesuaian menggunakan pilihan `-p` (atau `--pattern`), jika file pengujian anda dinamai berbeda dari pola `test*.py`:

```shell
$ ./manage.py test --pattern="tests_*.py"
```

If you press `Ctrl-C` while the tests are running, the test runner will
wait for the currently running test to complete and then exit gracefully.
During a graceful exit the test runner will output details of any test
failures, report on how many tests were run and how many errors and failures
were encountered, and destroy any test databases as usual. Thus pressing
`Ctrl-C` can be very useful if you forget to pass the [`--failfast`](/id/5.2/ref/django-admin/#cmdoption-test-failfast) option, notice that some tests are unexpectedly failing and
want to get details on the failures without waiting for the full test run to
complete.

If you do not want to wait for the currently running test to finish, you
can press `Ctrl-C` a second time and the test run will halt immediately,
but not gracefully. No details of the tests run before the interruption will
be reported, and any test databases created by the run will not be destroyed.

> **Percobaan dengan peringatan diadakan**
>
> Sebaiknya jalankan pengujian anda dengan peringatan Python diaktifkan: `python -Wa manage.py test`. Bendera `-Wa` memberi tahu Python untuk menampilkan peringatan penghentian. Django, seperti banyak pustaka Python lainnya, menggunakan peringatan ini untuk menandai ketika fitur akan hilang. Itu juga mungkin menandai area dalam kode anda yang tidak sepenuhnya salah tetapi bisa mendapat manfaat dari implementasi yang lebih baik.

### Basisdata percobaan

Tests that require a database (namely, model tests) will not use your "real"
(production) database. Separate, blank databases are created for the tests.

Regardless of whether the tests pass or fail, the test databases are destroyed
when all the tests have been executed.

You can prevent the test databases from being destroyed by using the
[`test --keepdb`](/id/5.2/ref/django-admin/#cmdoption-test-keepdb) option. This will preserve the test database between
runs. If the database does not exist, it will first be created. Any migrations
will also be applied in order to keep it up to date.

As described in the previous section, if a test run is forcefully interrupted,
the test database may not be destroyed. On the next run, you'll be asked
whether you want to reuse or destroy the database. Use the [`test
--noinput`](/id/5.2/ref/django-admin/#cmdoption-test-noinput) option to suppress that prompt and automatically destroy the
database. This can be useful when running tests on a continuous integration
server where tests may be interrupted by a timeout, for example.

The default test database names are created by prepending `test_` to the
value of each [`NAME`](/id/5.2/ref/settings/#std-setting-NAME) in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES). When using SQLite, the
tests will use an in-memory database by default (i.e., the database will be
created in memory, bypassing the filesystem entirely!). The [`TEST`](/id/5.2/ref/settings/#std-setting-DATABASE-TEST) dictionary in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES) offers a number of settings
to configure your test database. For example, if you want to use a different
database name, specify [`NAME`](/id/5.2/ref/settings/#std-setting-TEST_NAME) in the [`TEST`](/id/5.2/ref/settings/#std-setting-DATABASE-TEST) dictionary for any given database in [`DATABASES`](/id/5.2/ref/settings/#std-setting-DATABASES).

On PostgreSQL, [`USER`](/id/5.2/ref/settings/#std-setting-USER) will also need read access to the built-in
`postgres` database.

Aside from using a separate database, the test runner will otherwise
use all of the same database settings you have in your settings file:
[`ENGINE`](/id/5.2/ref/settings/#std-setting-DATABASE-ENGINE), [`USER`](/id/5.2/ref/settings/#std-setting-USER), [`HOST`](/id/5.2/ref/settings/#std-setting-HOST), etc. The
test database is created by the user specified by [`USER`](/id/5.2/ref/settings/#std-setting-USER), so you'll
need to make sure that the given user account has sufficient privileges to
create a new database on the system.

For fine-grained control over the character encoding of your test
database, use the [`CHARSET`](/id/5.2/ref/settings/#std-setting-TEST_CHARSET) TEST option. If you're using
MySQL, you can also use the [`COLLATION`](/id/5.2/ref/settings/#std-setting-TEST_COLLATION) option to
control the particular collation used by the test database. See the
[settings documentation](/id/5.2/ref/settings/) for details of these
and other advanced settings.

If using an SQLite in-memory database with SQLite, [shared cache](https://www.sqlite.org/sharedcache.html) is enabled, so you can write tests
with ability to share the database between threads.

> **Menemukan data dari basisdata produksi anda ketika menjalankan percobaan?**
>
> If your code attempts to access the database when its modules are compiled,
> this will occur *before* the test database is set up, with potentially
> unexpected results. For example, if you have a database query in
> module-level code and a real database exists, production data could pollute
> your tests. *It is a bad idea to have such import-time database queries in
> your code* anyway - rewrite your code so that it doesn't do this.
>
> Ini juga berlaku pada penerapan disesuaikan dari [`ready()`](/id/5.2/ref/applications/#django.apps.AppConfig.ready).

> **See also**
>
> [advanced multi-db testing topics](/id/5.2/topics/testing/advanced/#topics-testing-advanced-multidb).

### Urutkan dimana percobaan dijalankan

In order to guarantee that all `TestCase` code starts with a clean database,
the Django test runner reorders tests in the following way:

- Semua subkelas [`TestCase`](/id/5.2/topics/testing/tools/#django.test.TestCase) berjalan pertama.
- Then, all other Django-based tests (test case classes based on
  [`SimpleTestCase`](/id/5.2/topics/testing/tools/#django.test.SimpleTestCase), including
  [`TransactionTestCase`](/id/5.2/topics/testing/tools/#django.test.TransactionTestCase)) are run with no particular
  ordering guaranteed nor enforced among them.
- Then any other [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase) tests (including doctests) that may
  alter the database without restoring it to its original state are run.

> **Note**
>
> The new ordering of tests may reveal unexpected dependencies on test case
> ordering. This is the case with doctests that relied on state left in the
> database by a given [`TransactionTestCase`](/id/5.2/topics/testing/tools/#django.test.TransactionTestCase) test, they
> must be updated to be able to run independently.

> **Note**
>
> Failures detected when loading tests are ordered before all of the above
> for quicker feedback. This includes things like test modules that couldn't
> be found or that couldn't be loaded due to syntax errors.

You may randomize and/or reverse the execution order inside groups using the
[`test --shuffle`](/id/5.2/ref/django-admin/#cmdoption-test-shuffle) and [`--reverse`](/id/5.2/ref/django-admin/#cmdoption-test-reverse) options. This
can help with ensuring your tests are independent from each other.

### Rollback emulation

Any initial data loaded in migrations will only be available in `TestCase`
tests and not in `TransactionTestCase` tests, and additionally only on
backends where transactions are supported (the most important exception being
MyISAM). This is also true for tests which rely on `TransactionTestCase`
such as [`LiveServerTestCase`](/id/5.2/topics/testing/tools/#django.test.LiveServerTestCase) and
[`StaticLiveServerTestCase`](/id/5.2/ref/contrib/staticfiles/#django.contrib.staticfiles.testing.StaticLiveServerTestCase).

Django can reload that data for you on a per-testcase basis by
setting the `serialized_rollback` option to `True` in the body of the
`TestCase` or `TransactionTestCase`, but note that this will slow down
that test suite by approximately 3x.

Third-party apps or those developing against MyISAM will need to set this;
in general, however, you should be developing your own projects against a
transactional database and be using `TestCase` for most tests, and thus
not need this setting.

The initial serialization is usually very quick, but if you wish to exclude
some apps from this process (and speed up test runs slightly), you may add
those apps to [`TEST_NON_SERIALIZED_APPS`](/id/5.2/ref/settings/#std-setting-TEST_NON_SERIALIZED_APPS).

To prevent serialized data from being loaded twice, setting
`serialized_rollback=True` disables the
[`post_migrate`](/id/5.2/ref/signals/#django.db.models.signals.post_migrate) signal when flushing the test
database.

> **Changed in Django 5.2**
>
> For [`TransactionTestCase`](/id/5.2/topics/testing/tools/#django.test.TransactionTestCase), serialized migration data is made
> available during `setUpClass()`.

### Kondisi percobaan lain

Regardless of the value of the [`DEBUG`](/id/5.2/ref/settings/#std-setting-DEBUG) setting in your configuration
file, all Django tests run with [`DEBUG`](/id/5.2/ref/settings/#std-setting-DEBUG)=False. This is to ensure that
the observed output of your code matches what will be seen in a production
setting.

Cache tidak dihapus setelah setiap pengujian, dan menjalankan `manage.py test fooapp` dapat memasukkan data dari pengujian ke dalam cache sistem langsung jika anda menjalankan pengujian dalam produksi karena, tidak seperti basis data, "cache pengujian" terpisah tidak digunakan. Perilaku ini [may change](https://code.djangoproject.com/ticket/11505) di masa datang.

### Memahami keluaran percobaan

When you run your tests, you'll see a number of messages as the test runner
prepares itself. You can control the level of detail of these messages with the
`verbosity` option on the command line:

```shell
Creating test database...
Creating table myapp_animal
Creating table myapp_mineral
```

This tells you that the test runner is creating a test database, as described
in the previous section.

Once the test database has been created, Django will run your tests.
If everything goes well, you'll see something like this:

```shell
----------------------------------------------------------------------
Ran 22 tests in 0.221s

OK
```

If there are test failures, however, you'll see full details about which tests
failed:

```shell
======================================================================
FAIL: test_was_published_recently_with_future_poll (polls.tests.PollMethodTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/dev/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_poll
    self.assertIs(future_poll.was_published_recently(), False)
AssertionError: True is not False

----------------------------------------------------------------------
Ran 1 test in 0.003s

FAILED (failures=1)
```

A full explanation of this error output is beyond the scope of this document,
but it's pretty intuitive. You can consult the documentation of Python's
[`unittest`](https://docs.python.org/3/library/unittest.html#module-unittest) library for details.

Note that the return code for the test-runner script is 1 for any number of
failed tests (whether the failure was caused by an error, a failed assertion,
or an unexpected success). If all the tests pass, the return code is 0. This
feature is useful if you're using the test-runner script in a shell script and
need to test for success or failure at that level.

### Mempercepat percobaan

#### Menjalankan percobaan secara sejalan

As long as your tests are properly isolated, you can run them in parallel to
gain a speed up on multi-core hardware. See [`test --parallel`](/id/5.2/ref/django-admin/#cmdoption-test-parallel).

#### Campuran sandi

The default password hasher is rather slow by design. If you're authenticating
many users in your tests, you may want to use a custom settings file and set
the [`PASSWORD_HASHERS`](/id/5.2/ref/settings/#std-setting-PASSWORD_HASHERS) setting to a faster hashing algorithm:

```
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.MD5PasswordHasher",
]
```

Don't forget to also include in [`PASSWORD_HASHERS`](/id/5.2/ref/settings/#std-setting-PASSWORD_HASHERS) any hashing
algorithm used in fixtures, if any.

#### Preserving the test database

The [`test --keepdb`](/id/5.2/ref/django-admin/#cmdoption-test-keepdb) option preserves the test database between test
runs. It skips the create and destroy actions which can greatly decrease the
time to run tests.

#### Avoiding disk access for media files

The [`InMemoryStorage`](/id/5.2/ref/files/storage/#django.core.files.storage.InMemoryStorage) is a convenient way to
prevent disk access for media files. All data is kept in memory, then it gets
discarded after tests run.
