From f4df7d79611455b05ac386222b794fcebc452a79 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 30 Sep 2014 09:43:25 +0800 Subject: [PATCH 1/2] MDL-47492 behat: refer to table column indexes instead of names --- lib/tests/behat/behat_general.php | 67 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/lib/tests/behat/behat_general.php b/lib/tests/behat/behat_general.php index 9f8dc9392c6..a4ef1c82133 100644 --- a/lib/tests/behat/behat_general.php +++ b/lib/tests/behat/behat_general.php @@ -992,7 +992,7 @@ class behat_general extends behat_base { * @Then /^"(?P[^"]*)" row "(?P[^"]*)" column of "(?P[^"]*)" table should contain "(?P[^"]*)"$/ * @throws ElementNotFoundException * @param string $row row text which will be looked in. - * @param string $column column text to search + * @param string $column column text to search (or numeric value for the column position) * @param string $table table id/class/caption * @param string $value text to check. */ @@ -1004,42 +1004,41 @@ class behat_general extends behat_base { $valueliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($value); $columnliteral = $this->getSession()->getSelectorsHandler()->xpathLiteral($column); - // Header can be in thead or tbody (first row), following xpath should work. - $theadheaderxpath = "thead/tr[1]/th[(normalize-space(.)=" . $columnliteral . " or a[normalize-space(text())=" . - $columnliteral . "])]"; - $tbodyheaderxpath = "tbody/tr[1]/td[(normalize-space(.)=" . $columnliteral . " or a[normalize-space(text())=" . - $columnliteral . "])]"; + if (preg_match('/^-?(\d+)-?$/', $column, $columnasnumber)) { + // Column indicated as a number, just use it as position of the column. + $columnpositionxpath = "/child::*[position() = {$columnasnumber[1]}]"; + } else { + // Header can be in thead or tbody (first row), following xpath should work. + $theadheaderxpath = "thead/tr[1]/th[(normalize-space(.)=" . $columnliteral . " or a[normalize-space(text())=" . + $columnliteral . "])]"; + $tbodyheaderxpath = "tbody/tr[1]/td[(normalize-space(.)=" . $columnliteral . " or a[normalize-space(text())=" . + $columnliteral . "])]"; - // Check if column exists. - $columnheaderxpath = $tablexpath . "[" . $theadheaderxpath . " | " . $tbodyheaderxpath . "]"; - $columnheader = $this->getSession()->getDriver()->find($columnheaderxpath); - if (empty($columnheader)) { - $columnexceptionmsg = $column . '" in table "' . $table . '"'; - throw new ElementNotFoundException($this->getSession(), 'Column', null, $columnexceptionmsg); + // Check if column exists. + $columnheaderxpath = $tablexpath . "[" . $theadheaderxpath . " | " . $tbodyheaderxpath . "]"; + $columnheader = $this->getSession()->getDriver()->find($columnheaderxpath); + if (empty($columnheader)) { + $columnexceptionmsg = $column . '" in table "' . $table . '"'; + throw new ElementNotFoundException($this->getSession(), "\n$columnheaderxpath\n\n".'Column', null, $columnexceptionmsg); + } + // Following conditions were considered before finding column count. + // 1. Table header can be in thead/tr/th or tbody/tr/td[1]. + // 2. First column can have th (Gradebook -> user report), so having lenient sibling check. + $columnpositionxpath = "/child::*[position() = count(" . $tablexpath . "/" . $theadheaderxpath . + "/preceding-sibling::*) + 1]"; } // Check if value exists in specific row/column. // Get row xpath. $rowxpath = $tablexpath."/tbody/tr[th[normalize-space(.)=" . $rowliteral . "] | td[normalize-space(.)=" . $rowliteral . "]]"; - // Following conditions were considered before finding column count. - // 1. Table header can be in thead/tr/th or tbody/tr/td[1]. - // 2. First column can have th (Gradebook -> user report), so having lenient sibling check. - $columnpositionxpath = "/child::*[position() = count(" . $tablexpath . "/" . $theadheaderxpath . - "/preceding-sibling::*) + 1]"; $columnvaluexpath = $rowxpath . $columnpositionxpath . "[contains(normalize-space(.)," . $valueliteral . ")]"; + // Looks for the requested node inside the container node. $coumnnode = $this->getSession()->getDriver()->find($columnvaluexpath); if (empty($coumnnode)) { - // Check if tbody/tr[1] contains header selector. - $columnpositionxpath = "/child::*[position() = count(" . $tablexpath . "/" . $tbodyheaderxpath . - "/preceding-sibling::*) + 1]"; - $columnvaluexpath = $rowxpath . $columnpositionxpath . "[contains(normalize-space(.)," . $valueliteral . ")]"; - $coumnnode = $this->getSession()->getDriver()->find($columnvaluexpath); - if (empty($coumnnode)) { - $locatorexceptionmsg = $value . '" in "' . $row . '" row with column "' . $column; - throw new ElementNotFoundException($this->getSession(), 'Column value', null, $locatorexceptionmsg); - } + $locatorexceptionmsg = $value . '" in "' . $row . '" row with column "' . $column; + throw new ElementNotFoundException($this->getSession(), "\n$columnvaluexpath\n\n".'Column value', null, $locatorexceptionmsg); } } @@ -1071,6 +1070,10 @@ class behat_general extends behat_base { * Checks that the provided value exist in table. * More info in http://docs.moodle.org/dev/Acceptance_testing#Providing_values_to_steps. * + * First row may contain column headers or numeric indexes of the columns + * (syntax -1- is also considered to be column index). Column indexes are + * useful in case of multirow headers and/or presence of cells with colspan. + * * @Then /^the following should exist in the "(?P[^"]*)" table:$/ * @throws ExpectationException * @param string $table name of table @@ -1081,10 +1084,14 @@ class behat_general extends behat_base { public function following_should_exist_in_the_table($table, TableNode $data) { $datahash = $data->getHash(); - foreach ($datahash as $value) { - $row = array_shift($value); - foreach ($value as $column => $value) { - $this->row_column_of_table_should_contain($row, $column, $table, $value); + foreach ($datahash as $row) { + $firstcell = null; + foreach ($row as $column => $value) { + if ($firstcell === null) { + $firstcell = $value; + } else { + $this->row_column_of_table_should_contain($firstcell, $column, $table, $value); + } } } } From b1cdf13013f8cee6e67f4814bb63e045e14f8391 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 30 Sep 2014 09:43:44 +0800 Subject: [PATCH 2/2] MDL-47492 core_grades: Behat test for using scales and mingrade in gradebook --- grade/tests/behat/grade_scales.feature | 169 +++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 grade/tests/behat/grade_scales.feature diff --git a/grade/tests/behat/grade_scales.feature b/grade/tests/behat/grade_scales.feature new file mode 100644 index 00000000000..9deca6402c8 --- /dev/null +++ b/grade/tests/behat/grade_scales.feature @@ -0,0 +1,169 @@ +@core @core_grades +Feature: View gradebook when scales are used + In order to use scales to grade activities + As an teacher + I need to be able to view gradebook with scales + + Background: + Given I log in as "admin" + And I set the following administration settings values: + | grade_report_showranges | 1 | + | grade_aggregations_visible | Mean of grades,Weighted mean of grades,Simple weighted mean of grades,Mean of grades (with extra credits),Median of grades,Lowest grade,Highest grade,Mode of grades,Sum of grades | + And I navigate to "Scales" node in "Site administration > Grades" + And I press "Add a new scale" + And I set the following fields to these values: + | Name | Letterscale | + | Scale | F,D,C,B,A | + And I press "Save changes" + And I log out + And the following "courses" exist: + | fullname | shortname | + | Course 1 | C1 | + And the following "users" exist: + | username | firstname | lastname | email | idnumber | + | teacher1 | Teacher | 1 | teacher1@asd.com | t1 | + | student1 | Student | 1 | student1@asd.com | s1 | + | student2 | Student | 2 | student2@asd.com | s2 | + | student3 | Student | 3 | student3@asd.com | s3 | + | student4 | Student | 4 | student4@asd.com | s4 | + | student5 | Student | 5 | student5@asd.com | s5 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + | student2 | C1 | student | + | student3 | C1 | student | + | student4 | C1 | student | + | student5 | C1 | student | + And the following "grade categories" exist: + | fullname | course | + | Sub category 1 | C1 | + And the following "activities" exist: + | activity | course | idnumber | name | intro | gradecategory | + | assign | C1 | a1 | Test assignment one | Submit something! | Sub category 1 | + And I log in as "teacher1" + And I follow "Course 1" + And I follow "Test assignment one" + And I follow "Edit settings" + And I expand all fieldsets + And I set the field "grade[modgrade_type]" to "Scale" + And I set the field "grade[modgrade_scale]" to "Letterscale" + And I press "Save and display" + And I follow "View/grade all submissions" + And I click on "Grade Student 1" "link" in the "Student 1" "table_row" + And I set the field "Grade" to "A" + And I press "Save and show next" + And I set the field "Grade" to "B" + And I press "Save and show next" + And I set the field "Grade" to "C" + And I press "Save and show next" + And I set the field "Grade" to "D" + And I press "Save and show next" + And I set the field "Grade" to "F" + And I press "Save changes" + And I follow "Course 1" + And I follow "Grades" + And I turn editing mode on + + @javascript + Scenario: Test displaying scales in gradebook in aggregation method Sum of grades + When I follow "Edit Course 1" + And I set the field "Aggregation" to "Sum of grades" + And I press "Save changes" + And I follow "Edit Sub category 1" + And I set the field "Aggregation" to "Sum of grades" + And I press "Save changes" + And I turn editing mode off + Then the following should exist in the "user-grades" table: + | -1- | -4- | -5- | -6- | + | Student 1 | A | 5.00 | 5.00 | + | Student 2 | B | 4.00 | 4.00 | + | Student 3 | C | 3.00 | 3.00 | + | Student 4 | D | 2.00 | 2.00 | + | Student 5 | F | 1.00 | 1.00 | + And the following should exist in the "user-grades" table: + | -1- | -2- | -3- | -4- | + | Range | F–A | 0.00–5.00 | 0.00–5.00 | + | Overall average | C | 3.00 | 3.00 | + And I follow "User report" + And I set the field "Select all or one user" to "Student 3" + And I click on "Select all or one user" "select" + And the following should exist in the "user-grade" table: + | Grade item | Grade | Range | Percentage | + | Test assignment one | C | F–A | 50.00 % | + | Category total | 3.00 | 0–5 | 60.00 % | + | Course total | 3.00 | 0–5 | 60.00 % | + And I set the field "jump" to "Simple view" + And the following should exist in the "grade_edit_tree_table" table: + | Name | Max grade | + | Test assignment one | 5.00 | + | Category total | 5.00 | + | Course total | 5.00 | + And I log out + And I log in as "student2" + And I follow "Course 1" + And I follow "Grades" + And the following should exist in the "user-grade" table: + | Grade item | Grade | Range | Percentage | + | Test assignment one | B | F–A | 75.00 % | + | Category total | 4.00 | 0–5 | 80.00 % | + | Course total | 4.00 | 0–5 | 80.00 % | + + @javascript + Scenario Outline: Test displaying scales in gradebook in all other aggregation methods + When I follow "Edit Course 1" + And I set the field "Aggregation" to "" + And I press "Save changes" + And I follow "Edit Sub category 1" + And I expand all fieldsets + And I set the field "Aggregation" to "" + And I set the field "Category name" to "Sub category ()" + And I set the field "Maximum grade" to "5" + And I set the field "Minimum grade" to "1" + And I press "Save changes" + And I turn editing mode off + Then the following should exist in the "user-grades" table: + | -1- | -4- | -5- | -6- | + | Student 1 | A | 5.00 | | + | Student 2 | B | 4.00 | | + | Student 3 | C | 3.00 | | + | Student 4 | D | 2.00 | | + | Student 5 | F | 1.00 | | + And the following should exist in the "user-grades" table: + | -1- | -2- | -3- | -4- | + | Range | F–A | 1.00–5.00 | 0.00–100.00 | + | Overall average | C | 3.00 | | + And I follow "User report" + And I set the field "Select all or one user" to "Student 3" + And I click on "Select all or one user" "select" + And the following should exist in the "user-grade" table: + | Grade item | Grade | Range | Percentage | + | Test assignment one | C | F–A | 50.00 % | + | Category total | 3.00 | 1–5 | 50.00 % | + | Course total | | 0–100 | | + And I set the field "jump" to "Simple view" + And the following should exist in the "grade_edit_tree_table" table: + | Name | Max grade | + | Test assignment one | A (5) | + | Category total | | + | Course total | | + And I log out + And I log in as "student2" + And I follow "Course 1" + And I follow "Grades" + And the following should exist in the "user-grade" table: + | Grade item | Grade | Range | Percentage | + | Test assignment one | B | F–A | 75.00 % | + | Category total | 4.00 | 1–5 | 75.00 % | + | Course total | | 0–100 | | + + Examples: + | aggregation | coursetotal1 | coursetotal2 | coursetotal3 | coursetotal4 | coursetotal5 |overallavg | courseperc2 | courseperc3 | + | Mean of grades | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Weighted mean of grades | - | - | - | - | - | - | - | - | + | Simple weighted mean of grades | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Mean of grades (with extra credits) | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Median of grades | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Lowest grade | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Highest grade | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % | + | Mode of grades | 100.00 | 75.00 | 50.00 | 25.00 | 0.00 | 50.00 | 75.00 % | 50.00 % |