management command to create test users (#25449)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
""" Shared behavior between create_test_users and create_random_users """
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
from lms.djangoapps.instructor.access import allow_access
|
||||
from openedx.core.djangoapps.user_authn.views.registration_form import AccountCreationForm
|
||||
from student.helpers import do_create_account
|
||||
from student.models import CourseEnrollment
|
||||
|
||||
|
||||
def create_users(
|
||||
course_key,
|
||||
user_data,
|
||||
enrollment_mode=None,
|
||||
course_staff=False,
|
||||
activate=False
|
||||
):
|
||||
"""Create users, enrolling them in course_key if it's not None"""
|
||||
for single_user_data in user_data:
|
||||
account_creation_form = AccountCreationForm(
|
||||
data=single_user_data,
|
||||
tos_required=False
|
||||
)
|
||||
|
||||
(user, _, _) = do_create_account(account_creation_form)
|
||||
|
||||
if activate:
|
||||
user.is_active = True
|
||||
user.save()
|
||||
|
||||
if course_key is not None:
|
||||
CourseEnrollment.enroll(user, course_key, mode=enrollment_mode)
|
||||
if course_staff:
|
||||
course = modulestore().get_course(course_key, depth=1)
|
||||
allow_access(course, user, 'staff', send_email=False)
|
||||
|
||||
if course_key and course_staff:
|
||||
print('Created user {} as course staff'.format(user.username))
|
||||
else:
|
||||
print('Created user {}'.format(user.username))
|
||||
@@ -1,42 +1,23 @@
|
||||
"""
|
||||
A script to create some dummy users
|
||||
"""
|
||||
|
||||
|
||||
import uuid
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six.moves import range
|
||||
|
||||
from openedx.core.djangoapps.user_authn.views.registration_form import AccountCreationForm
|
||||
from student.helpers import do_create_account
|
||||
from student.models import CourseEnrollment
|
||||
from common.djangoapps.student.management.commands._create_users import create_users
|
||||
|
||||
|
||||
def make_random_form():
|
||||
"""
|
||||
Generate unique user data for dummy users.
|
||||
"""
|
||||
identification = uuid.uuid4().hex[:8]
|
||||
return AccountCreationForm(
|
||||
data={
|
||||
def random_user_data_generator(num_users):
|
||||
for _ in range(num_users):
|
||||
identification = uuid.uuid4().hex[:8]
|
||||
yield {
|
||||
'username': 'user_{id}'.format(id=identification),
|
||||
'email': 'email_{id}@example.com'.format(id=identification),
|
||||
'password': '12345',
|
||||
'name': 'User {id}'.format(id=identification),
|
||||
},
|
||||
tos_required=False
|
||||
)
|
||||
|
||||
|
||||
def create(num, course_key):
|
||||
"""Create num users, enrolling them in course_key if it's not None"""
|
||||
for __ in range(num):
|
||||
(user, _, _) = do_create_account(make_random_form())
|
||||
if course_key is not None:
|
||||
CourseEnrollment.enroll(user, course_key)
|
||||
print('Created user {}'.format(user.username))
|
||||
}
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -61,4 +42,4 @@ Examples:
|
||||
def handle(self, *args, **options):
|
||||
num = options['num_users']
|
||||
course_key = CourseKey.from_string(options['course_key']) if options['course_key'] else None
|
||||
create(num, course_key)
|
||||
create_users(course_key, random_user_data_generator(num))
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
""" Management command to create test users """
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from common.djangoapps.student.management.commands._create_users import create_users
|
||||
|
||||
|
||||
def user_info_generator(usernames, password, domain):
|
||||
for username in usernames:
|
||||
yield {
|
||||
'username': username,
|
||||
'email': '{username}@{domain}'.format(username=username, domain=domain),
|
||||
'password': password,
|
||||
'name': username,
|
||||
}
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
Create test users with the given usernames and modes and enrolls them in the given course.
|
||||
|
||||
Usage: create_test_users.py username1 ... usernameN [--course] [--mode] [--password] [--domain] [--course_staff]
|
||||
|
||||
Examples:
|
||||
create_test_users.py
|
||||
create_test_users.py user1 --course MITx/6.002x/2012_Fall --domain testuniversity.edu
|
||||
create_test_users.py testmasters1 testmasters2 --course HarvardX/CS50x/2012 --mode masters
|
||||
create_test_users.py testcoursestaff1 testcoursestaff2 --course DemoX/MS12/1 --course_staff --password testpassword
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'usernames',
|
||||
help='Usernames to use for created users.',
|
||||
nargs='+'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--course',
|
||||
help='Add newly created users to this course',
|
||||
type=CourseKey.from_string
|
||||
)
|
||||
parser.add_argument(
|
||||
'--mode',
|
||||
help='The enrollment mode for the test users. If --course is not provided, this is ignored',
|
||||
default='audit',
|
||||
choices=CourseMode.ALL_MODES
|
||||
)
|
||||
parser.add_argument(
|
||||
'--password',
|
||||
help='Password to use for all created users.',
|
||||
default='12345'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--domain',
|
||||
help='Domain for email addresses for created accounts',
|
||||
default='example.com'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--course_staff',
|
||||
help=(
|
||||
'If present, users are created as course staff. --mode, if specified, is ignored. '
|
||||
'If --course is not provided, this is ignored'
|
||||
),
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
course_key = options['course']
|
||||
course_staff = options['course_staff'] if course_key else None
|
||||
enrollment_mode = options['mode'] if course_key and not course_staff else None
|
||||
create_users(
|
||||
course_key,
|
||||
user_info_generator(
|
||||
options['usernames'],
|
||||
options['password'],
|
||||
options['domain']
|
||||
),
|
||||
enrollment_mode=enrollment_mode,
|
||||
course_staff=course_staff,
|
||||
activate=True
|
||||
)
|
||||
@@ -0,0 +1,206 @@
|
||||
"""
|
||||
Test the create_random_users command line script
|
||||
"""
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import CommandError
|
||||
from opaque_keys import InvalidKeyError
|
||||
from six import text_type
|
||||
|
||||
from student.helpers import AccountValidationError
|
||||
from student.models import CourseAccessRole, CourseEnrollment
|
||||
from student.roles import CourseStaffRole
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CreateTestUsersTestCase(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test creating users via command line, with various options
|
||||
"""
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.course_id = text_type(self.course.id)
|
||||
self.user_model = get_user_model()
|
||||
self.num_users_start = len(self.user_model.objects.all())
|
||||
|
||||
def call_command(self, users, course=None, mode=None, password=None, domain=None, course_staff=False):
|
||||
""" Helper method to call the management command with various arguments """
|
||||
args = ['create_test_users']
|
||||
args.extend(users)
|
||||
if course:
|
||||
args.extend(['--course', course])
|
||||
if mode:
|
||||
args.extend(['--mode', mode])
|
||||
if password:
|
||||
args.extend(['--password', password])
|
||||
if domain:
|
||||
args.extend(['--domain', domain])
|
||||
if course_staff:
|
||||
args.append('--course_staff')
|
||||
call_command(*args)
|
||||
|
||||
def test_create_users(self):
|
||||
"""
|
||||
Calls the command with a list of usernames to create users.
|
||||
"""
|
||||
usernames = ['test_create_users_u1', 'test_create_users_u2']
|
||||
|
||||
# Check users don't already exist
|
||||
self.assertEqual(self.user_model.objects.filter(username__in=usernames).count(), 0)
|
||||
|
||||
self.call_command(usernames)
|
||||
|
||||
# Verify users were created, are active, and were created with default settings
|
||||
users = self.user_model.objects.filter(username__in=usernames).all()
|
||||
self.assertEqual(len(users), len(usernames))
|
||||
for user in users:
|
||||
self.assertTrue(user.is_active)
|
||||
self.assertEqual(user.email, '{}@example.com'.format(user.username))
|
||||
self.assertTrue(self.client.login(username=user.username, password='12345'))
|
||||
|
||||
self.assertFalse(CourseEnrollment.objects.filter(user__in=users).exists())
|
||||
|
||||
def test_create_user__username_taken(self):
|
||||
"""
|
||||
Try to create a user with a taken username
|
||||
"""
|
||||
username = 'user1'
|
||||
# Create a user with the given username but a different email
|
||||
self.user_model.objects.create_user(username, 'taken_email@example.com', '12345')
|
||||
with self.assertRaisesMessage(AccountValidationError, "'user1' already exists"):
|
||||
self.call_command([username])
|
||||
|
||||
def test_create_user_with_course(self):
|
||||
"""
|
||||
Create users and have them enroll in a course
|
||||
"""
|
||||
usernames = ['username1', 'username2']
|
||||
self.call_command(usernames, course=self.course_id)
|
||||
|
||||
# Check that the users exist and were enrolled in the course with the default settings
|
||||
users = self.user_model.objects.filter(username__in=usernames).all()
|
||||
self.assertEqual(len(users), len(usernames))
|
||||
for user in users:
|
||||
enrollment = CourseEnrollment.get_enrollment(user, self.course.id)
|
||||
self.assertEqual(enrollment.mode, 'audit')
|
||||
self.assertFalse(CourseStaffRole(self.course.id).has_user(user))
|
||||
|
||||
def test_create_user_with_course__bad_course(self):
|
||||
"""
|
||||
The test passes in a bad course id, no users or CourseEnrollments should be created
|
||||
"""
|
||||
with pytest.raises(InvalidKeyError):
|
||||
self.call_command(['username1'], course='invalid_course_id')
|
||||
|
||||
# Verify no users have been created
|
||||
self.assertEqual(self.num_users_start, len(self.user_model.objects.all()))
|
||||
# Verify that no one is enrolled in the course
|
||||
self.assertEqual(len(CourseEnrollment.objects.filter(course__id=self.course.id)), 0)
|
||||
|
||||
def test_create_user__mode(self):
|
||||
"""
|
||||
Create a test for a user in verified mode.
|
||||
"""
|
||||
# Create a user in verified rather than default audit
|
||||
username = 'user1'
|
||||
self.call_command([username], course=self.course_id, mode='verified')
|
||||
|
||||
# Verify enrollment
|
||||
user = self.user_model.objects.get(username='user1')
|
||||
enrollment = CourseEnrollment.get_enrollment(user, self.course.id)
|
||||
self.assertEqual(enrollment.mode, 'verified')
|
||||
|
||||
def test_create_user__mode__invalid(self):
|
||||
"""
|
||||
Create a test for a user in an invalid mode.
|
||||
"""
|
||||
username = 'user1'
|
||||
with self.assertRaisesMessage(CommandError, "argument --mode: invalid choice: 'cataclysmic'"):
|
||||
self.call_command([username], course=self.course_id, mode='cataclysmic')
|
||||
|
||||
def test_create_user__domain(self):
|
||||
"""
|
||||
Create a test user with a specific email domain
|
||||
"""
|
||||
username = 'user1'
|
||||
domain = 'another-super-example.horse'
|
||||
self.call_command([username], domain=domain)
|
||||
|
||||
user = self.user_model.objects.get(username=username)
|
||||
self.assertEqual(user.email, '{}@{}'.format(username, domain))
|
||||
|
||||
def test_create_user__email_taken(self):
|
||||
"""
|
||||
Try to create a user with a taken email
|
||||
"""
|
||||
existing_username = 'some-username'
|
||||
self.user_model.objects.create_user(existing_username, 'taken_email@example.com', '12345')
|
||||
with self.assertRaises(ValidationError):
|
||||
self.call_command(['taken_email'], domain='example.com')
|
||||
|
||||
def test_create_user__bad_domain(self):
|
||||
"""
|
||||
Try to create a user with a bad email domain
|
||||
"""
|
||||
username = 'user1'
|
||||
with self.assertRaises(ValidationError):
|
||||
self.call_command([username], domain='this-aint-no-domain')
|
||||
self.assertFalse(self.user_model.objects.filter(username=username).exists())
|
||||
|
||||
def test_create_user__password(self):
|
||||
"""
|
||||
Create test user with specified password
|
||||
"""
|
||||
username = 'user1'
|
||||
password = 'somepassword1234512341241234'
|
||||
self.call_command([username], password=password)
|
||||
|
||||
self.assertTrue(self.client.login(username=username, password=password))
|
||||
|
||||
def test_create_user__password__error(self):
|
||||
"""
|
||||
Try to create user with a password that's too short
|
||||
"""
|
||||
self.call_command(['user1'], password='a')
|
||||
|
||||
def test_create_user__course_staff(self):
|
||||
"""
|
||||
Create a user and set them as course staff
|
||||
"""
|
||||
username = 'user1'
|
||||
self.call_command([username], course=self.course_id, course_staff=True)
|
||||
|
||||
user = self.user_model.objects.get(username=username)
|
||||
enrollment = CourseEnrollment.get_enrollment(user, self.course.id)
|
||||
self.assertEqual(enrollment.mode, 'audit')
|
||||
self.assertTrue(CourseStaffRole(self.course.id).has_user(user))
|
||||
|
||||
def test_create_user__course_staff__ignore_mode(self):
|
||||
"""
|
||||
Test that mode is ignored when --course_staff is specified
|
||||
"""
|
||||
username = 'user1'
|
||||
self.call_command([username], course=self.course_id, course_staff=True, mode='verified')
|
||||
|
||||
user = self.user_model.objects.get(username=username)
|
||||
enrollment = CourseEnrollment.get_enrollment(user, self.course.id)
|
||||
self.assertEqual(enrollment.mode, 'audit')
|
||||
self.assertTrue(CourseStaffRole(self.course.id).has_user(user))
|
||||
|
||||
def test_create_user__ignore_course_staff_and_mode_when_no_course(self):
|
||||
"""
|
||||
Test that --course_staff and --mode are ignored when there is no --course
|
||||
"""
|
||||
username = 'user1'
|
||||
self.call_command([username], course_staff=True, mode='verified')
|
||||
|
||||
user = self.user_model.objects.get(username=username)
|
||||
self.assertFalse(CourseAccessRole.objects.filter(user=user).exists())
|
||||
self.assertFalse(CourseEnrollment.objects.filter(user=user).exists())
|
||||
Reference in New Issue
Block a user