management command to create test users (#25449)

This commit is contained in:
Jansen Kantor
2020-10-29 14:55:52 -04:00
committed by GitHub
parent 1a1c04e28a
commit 7d40793967
4 changed files with 334 additions and 26 deletions

View File

@@ -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))

View File

@@ -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))

View File

@@ -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
)

View File

@@ -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())